home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / INTERNET / SITES / LITTLE / P3SRC.ZIP / ATARI / LIGHTING.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-18  |  86.8 KB  |  3,377 lines

  1. /****************************************************************************
  2. *                   lighting.c
  3. *
  4. *  This module calculates lighting properties like ambient, diffuse, specular,
  5. *  reflection, refraction, etc.
  6. *
  7. *  from Persistence of Vision(tm) Ray Tracer
  8. *  Copyright 1996 Persistence of Vision Team
  9. *---------------------------------------------------------------------------
  10. *  NOTICE: This source code file is provided so that users may experiment
  11. *  with enhancements to POV-Ray and to port the software to platforms other
  12. *  than those supported by the POV-Ray Team.  There are strict rules under
  13. *  which you are permitted to use this file.  The rules are in the file
  14. *  named POVLEGAL.DOC which should be distributed with this file. If
  15. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  16. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  17. *  Forum.  The latest version of POV-Ray may be found there as well.
  18. *
  19. * This program is based on the popular DKB raytracer version 2.12.
  20. * DKBTrace was originally written by David K. Buck.
  21. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  22. *
  23. *****************************************************************************/
  24.  
  25. #include "frame.h"
  26. #include "vector.h"
  27. #include "povproto.h"
  28. #include "blob.h"
  29. #include "bbox.h"
  30. #include "colour.h"
  31. #include "halos.h"
  32. #include "image.h"
  33. #include "lbuffer.h"
  34. #include "lighting.h"
  35. #include "mesh.h"
  36. #include "normal.h"
  37. #include "objects.h"
  38. #include "octree.h"
  39. #include "pattern.h"  /* [CEY 10/94] */
  40. #include "pigment.h"
  41. #include "povray.h"
  42. #include "radiosit.h"
  43. #include "ray.h"
  44. #include "render.h"
  45. #include "texture.h"
  46.  
  47.  
  48.  
  49. /*****************************************************************************
  50. * Local preprocessor defines
  51. ******************************************************************************/
  52.  
  53. #define BLACK_LEVEL 0.003
  54.  
  55. /*
  56.  * "Small_Tolerance" is just too tight for higher order polynomial equations.
  57.  * this value should probably be a variable of some sort, but for now just
  58.  * use a reasonably small value.  If people render real small objects real
  59.  * close to each other then there may be some shading problems.  Otherwise
  60.  * having SHADOW_TOLERANCE as large as this won't affect images.
  61.  */
  62.  
  63. #define SHADOW_TOLERANCE 1.0e-3
  64.  
  65. /* Number of inital entries in the texture and weight list. */
  66.  
  67. #define NUMBER_OF_ENTRIES 16
  68.  
  69.  
  70.  
  71. /*****************************************************************************
  72. * Local typedefs
  73. ******************************************************************************/
  74.  
  75. /*
  76.  * List to store light colours during shadow testing
  77.  * to avoid repeated testing with layered textures.
  78.  */
  79.  
  80. typedef struct Light_Tested_Struct LIGHT_TESTED;
  81.  
  82. struct Light_Tested_Struct
  83. {
  84.   int    Tested;
  85.   COLOUR Colour;
  86. };
  87.  
  88.  
  89.  
  90. /*****************************************************************************
  91. * Local variables
  92. ******************************************************************************/
  93.  
  94. static LIGHT_TESTED *Light_List;
  95. static TEXTURE **Texture_List;
  96. static DBL *Weight_List;
  97.  
  98. static int Number_Of_Textures_And_Weights;
  99.  
  100.  
  101.  
  102. /*****************************************************************************
  103. * Static functions
  104. ******************************************************************************/
  105.  
  106. static void block_area_light PARAMS((LIGHT_SOURCE *Light_Source,
  107.   DBL *Light_Source_Depth, RAY *Light_Source_Ray, RAY *Eye_Ray,
  108.   VECTOR IPoint, COLOUR Light_Colour, int u1, int v1, int u2, int v2, int Level));
  109.  
  110. static void block_point_light PARAMS((LIGHT_SOURCE *Light_Source,
  111.   DBL *Light_Source_Depth, RAY *Light_Source_Ray, COLOUR Light_Colour));
  112.  
  113. static void block_point_light_LBuffer PARAMS((LIGHT_SOURCE *Light_Source,
  114.   DBL *Light_Source_Depth, RAY *Light_Source_Ray, COLOUR Light_Colour));
  115.  
  116. static void do_light PARAMS((LIGHT_SOURCE *Light_Source,
  117.   DBL *Light_Source_Depth, RAY *Light_Source_Ray, RAY *Eye_Ray, VECTOR IPoint,
  118.   COLOUR Light_Colour));
  119.  
  120. static int do_blocking PARAMS((INTERSECTION *Local_Intersection,
  121.   RAY *Light_Source_Ray, COLOUR Light_Colour, ISTACK *Local_Stack));
  122.  
  123. static void do_phong PARAMS((FINISH *Finish, RAY *Light_Source_Ray,
  124.   VECTOR Eye, VECTOR Layer_Normal, COLOUR Colour, COLOUR Light_Colour,
  125.   COLOUR Layer_Texture_Colour));
  126.  
  127. static void do_specular PARAMS((FINISH *Finish, RAY *Light_Source_Ray,
  128.   VECTOR REye, VECTOR Layer_Normal, COLOUR Colour, COLOUR Light_Colour,
  129.   COLOUR Layer_Pigment_Colour));
  130.  
  131. static void do_diffuse PARAMS((FINISH *Finish, RAY *Light_Source_Ray,
  132.   VECTOR Layer_Normal, COLOUR Colour, COLOUR Light_Colour,
  133.   COLOUR Layer_Pigment_Colour, DBL Attenuation));
  134.  
  135. static void do_irid PARAMS((FINISH *Finish, RAY *Light_Source_Ray,
  136.   VECTOR Layer_Normal, VECTOR IPoint, COLOUR Colour));
  137.  
  138. static void Diffuse PARAMS((FINISH *Finish, VECTOR IPoint, RAY *Eye, VECTOR Layer_Normal,
  139.   COLOUR Layer_Pigment_Colour, COLOUR Colour,DBL Attenuation, OBJECT *Object));
  140.  
  141. static void Reflect PARAMS((RGB Reflection, VECTOR IPoint, RAY *Ray, VECTOR Layer_Normal, COLOUR Colour, DBL Weight));
  142.  
  143. static void Refract PARAMS((OBJECT *Object, TEXTURE *Texture, VECTOR IPoint,
  144.   RAY *Ray, VECTOR Layer_Normal, COLOUR Colour, DBL Weight));
  145.  
  146. static void filter_shadow_ray PARAMS((INTERSECTION *Ray_Intersection,
  147.   RAY *Light_Source_Ray, COLOUR Colour));
  148.  
  149. static int create_texture_list PARAMS((INTERSECTION *Ray_Intersection));
  150.  
  151. static void do_texture_map PARAMS((COLOUR Result_Colour,
  152.   TEXTURE *Texture, VECTOR IPoint, VECTOR Raw_Normal, RAY *Ray, DBL Weight,
  153.   INTERSECTION *Ray_Intersection, int Shadow_Flag));
  154.  
  155. static void average_textures PARAMS((COLOUR Result_Colour,
  156.   TEXTURE *Texture, VECTOR IPoint, VECTOR Raw_Normal, RAY *Ray, DBL Weight,
  157.   INTERSECTION *Ray_Intersection, int Shadow_Flag));
  158.  
  159. static void compute_lighted_texture PARAMS((COLOUR Result_Colour,
  160.   TEXTURE *Texture, VECTOR IPoint, VECTOR Raw_Normal, RAY *Ray, DBL Weight,
  161.   INTERSECTION *Ray_Intersection));
  162.  
  163. static void compute_shadow_texture PARAMS((COLOUR Filter_Colour,
  164.   TEXTURE *Texture, VECTOR IPoint, VECTOR Raw_Normal, RAY *Ray,
  165.   INTERSECTION *Ray_Intersection));
  166.  
  167. static void block_light_source PARAMS((LIGHT_SOURCE *Light,
  168.   DBL Depth, RAY *Light_Source_Ray, RAY *Eye_Ray, VECTOR P, COLOUR Colour));
  169.  
  170. static void do_light_ray_atmosphere PARAMS((RAY *Light_Source_Ray,
  171.   INTERSECTION *Ray_Intersection, TEXTURE *Texture, COLOUR Colour, int Valid_Object));
  172.  
  173.  
  174.  
  175. /*****************************************************************************
  176. *
  177. * FUNCTION
  178. *
  179. *   Initialize_Lighting_Code
  180. *
  181. * INPUT
  182. *
  183. * OUTPUT
  184. *   
  185. * RETURNS
  186. *   
  187. * AUTHOR
  188. *
  189. *   Dieter Bayer
  190. *   
  191. * DESCRIPTION
  192. *
  193. *   Allocate lists needed during lighting calculations.
  194. *
  195. * CHANGES
  196. *
  197. *   Sep 1994 : Creation.
  198. *
  199. *   Okt 1994 : Added initialization of Light_List and test if there are
  200. *              any light sources in the scene. [DB]
  201. *
  202. ******************************************************************************/
  203.  
  204. void Initialize_Lighting_Code()
  205. {
  206.   int i;
  207.  
  208.   Light_List = NULL;
  209.   Texture_List = NULL;
  210.   Weight_List  = NULL;
  211.  
  212.   /* Allocate memory for light list. */
  213.  
  214.   if (Frame.Number_Of_Light_Sources > 0)
  215.   {
  216.     Light_List = (LIGHT_TESTED *)POV_MALLOC(Frame.Number_Of_Light_Sources*sizeof(LIGHT_TESTED), "temporary light list");
  217.  
  218.     for (i = 0; i < Frame.Number_Of_Light_Sources; i++)
  219.     {
  220.       Light_List[i].Tested = FALSE;
  221.  
  222.       Make_ColourA(Light_List[i].Colour, 0.0, 0.0, 0.0, 0.0, 0.0);
  223.     }
  224.   }
  225.  
  226.   /* Allocate memory for texture and weight list. */
  227.  
  228.   Number_Of_Textures_And_Weights = NUMBER_OF_ENTRIES;
  229.  
  230.   Texture_List = (TEXTURE **)POV_MALLOC(Number_Of_Textures_And_Weights*sizeof(TEXTURE *), "texture list");
  231.  
  232.   Weight_List = (DBL *)POV_MALLOC(Number_Of_Textures_And_Weights*sizeof(DBL), "weight list");
  233. }
  234.  
  235.  
  236.  
  237. /*****************************************************************************
  238. *
  239. * FUNCTION
  240. *
  241. *   Reinitialize_Lighting_Code
  242. *
  243. * INPUT
  244. *
  245. *   Number_Of_Entries - New number of entries in the texture/weight lists
  246. *   
  247. * OUTPUT
  248. *
  249. * RETURNS
  250. *   
  251. * AUTHOR
  252. *
  253. *   Dieter Bayer
  254. *   
  255. * DESCRIPTION
  256. *
  257. *   Resize variable lists needed during lighting calculation.
  258. *
  259. * CHANGES
  260. *
  261. *   Jul 1995 : Creation.
  262. *
  263. *   Mar 1996 : We have to pass pointers to the lists to resize because during
  264. *              resizing the pointers to the lists change and thus the calling
  265. *              functions does not longer know where the lists are if the
  266. *              pointers to the lists where passed to it using arguments. [DB]
  267. *
  268. ******************************************************************************/
  269.  
  270. void Reinitialize_Lighting_Code(Number_Of_Entries, Textures, Weights)
  271. int Number_Of_Entries;
  272. TEXTURE ***Textures;
  273. DBL **Weights;
  274. {
  275.   if (Number_Of_Entries > Number_Of_Textures_And_Weights)
  276.   {
  277.     if (Number_Of_Entries >= INT_MAX / 2)
  278.     {
  279.       Error("Too many entries in texture and weight lists.\n");
  280.     }
  281.  
  282.     Number_Of_Textures_And_Weights = Number_Of_Entries;
  283.  
  284.     Texture_List = (TEXTURE **)POV_REALLOC(Texture_List, Number_Of_Textures_And_Weights*sizeof(TEXTURE *), "texture list");
  285.  
  286.     Weight_List = (DBL *)POV_REALLOC(Weight_List, Number_Of_Textures_And_Weights*sizeof(DBL), "weight list");
  287.  
  288.     *Textures = Texture_List;
  289.     *Weights  = Weight_List;
  290.   }
  291. }
  292.  
  293.  
  294.  
  295. /*****************************************************************************
  296. *
  297. * FUNCTION
  298. *
  299. *   Deinitialize_Lighting_Code
  300. *
  301. * INPUT
  302. *   
  303. * OUTPUT
  304. *   
  305. * RETURNS
  306. *   
  307. * AUTHOR
  308. *
  309. *   Dieter Bayer
  310. *   
  311. * DESCRIPTION
  312. *
  313. *   Destroy all lists needed during lighting calculation.
  314. *
  315. * CHANGES
  316. *
  317. *   Sep 1994 : Creation.
  318. *
  319. *   Jul 1995 : Added code to free local texture and weight lists. [DB]
  320. *
  321. ******************************************************************************/
  322.  
  323. void Deinitialize_Lighting_Code()
  324. {
  325.   if (Light_List != NULL)
  326.   {
  327.     POV_FREE(Light_List);
  328.   }
  329.  
  330.   if (Texture_List != NULL)
  331.   {
  332.     POV_FREE(Texture_List);
  333.   }
  334.  
  335.   if (Weight_List != NULL)
  336.   {
  337.     POV_FREE(Weight_List);
  338.   }
  339.  
  340.   Light_List   = NULL;
  341.   Texture_List = NULL;
  342.   Weight_List  = NULL;
  343. }
  344.  
  345.  
  346.  
  347. /*****************************************************************************
  348. *
  349. * FUNCTION
  350. *
  351. *   Determine_Apparent_Colour
  352. *
  353. * INPUT
  354. *
  355. *   Ray_Intersection - info on where ray hit & object it hit
  356. *   Ray              - the ray from which object is seen
  357. *   Weight           - Automatic depth control value
  358. *
  359. * OUTPUT
  360. *
  361. *   Colour           - resulting color is added to given color. The RGB
  362. *                      components are significant. The transmittance channel
  363. *                      is used as an alpha channel.
  364. *
  365. * RETURNS
  366. *
  367. * AUTHOR
  368. *
  369. *   POV-Ray Team
  370. *
  371. * DESCRIPTION
  372. *
  373. *   Given an intersection point, a ray, add that point's visible color
  374. *   to the given colour and return it.  This routine just does preliminary
  375. *   initializations and calls to set up the multi-texture blob list if any.
  376. *   Then it calls do_texture_map which in turn calls compute_lighted_texture
  377. *   to do the actual lighting calculations.  These functions were seperated
  378. *   from this function because do_texture_map may need to call itself
  379. *   recursively.
  380. *
  381. * CHANGES
  382. *
  383. *   Sep 1994 : Code for multi-textured blobs added. [DB]
  384. *
  385. *   Nov 1994 : Moved calls to Fog and Rainbow into tracing functions. [DB]
  386. *
  387. *   Jan 1995 : Moved much of code to do_texture_map and
  388. *              compute_lighted_texture [CEY]
  389. *
  390. *   Jul 1995 : Added code to support alpha channel. [DB]
  391. *
  392. *   Mar 1996 : Fixed severe bug (weight and texture lists were not saved) [DB]
  393. *
  394. ******************************************************************************/
  395.  
  396. void Determine_Apparent_Colour(Ray_Intersection, Colour, Ray, Weight)
  397. INTERSECTION *Ray_Intersection;
  398. COLOUR Colour;
  399. RAY *Ray;
  400. DBL Weight;
  401. {
  402.   int i, Texture_Count;
  403.   size_t savelights_size, save_tw_size;
  404.   DBL *save_Weights = NULL;
  405.   COLOUR C1;
  406.   VECTOR Raw_Normal;
  407.   VECTOR IPoint;
  408.   TEXTURE *Texture, **save_Textures = NULL;
  409.   LIGHT_TESTED *savelights = NULL;
  410.  
  411.   Assign_Vector(IPoint,Ray_Intersection->IPoint);
  412.  
  413.   /*
  414.    * Save existing light list if any. If we are not top level in recursion
  415.    * depth, this information may be reused by upper level of trace.
  416.    */
  417.  
  418.   savelights_size = (size_t)(Frame.Number_Of_Light_Sources*sizeof(LIGHT_TESTED));
  419.  
  420.   if (savelights_size > 0)
  421.   {
  422.     savelights = (LIGHT_TESTED *)POV_MALLOC(savelights_size, "Light list stack");
  423.  
  424.     memcpy(savelights, Light_List, savelights_size);
  425.   }
  426.  
  427.   /* Init light list. */
  428.  
  429.   for (i = 0; i < Frame.Number_Of_Light_Sources; i++)
  430.   {
  431.     Light_List[i].Tested = FALSE;
  432.   }
  433.  
  434.   /* Get the normal to the surface */
  435.  
  436.   Normal(Raw_Normal, Ray_Intersection->Object, Ray_Intersection);
  437.  
  438.   /*
  439.    * Save texture and weight lists.
  440.    */
  441.  
  442.   save_tw_size = (size_t)Number_Of_Textures_And_Weights;
  443.  
  444.   if (save_tw_size > 0)
  445.   {
  446.     save_Weights = (DBL *)POV_MALLOC(save_tw_size * sizeof(DBL), "Weight list stack");
  447.  
  448.     memcpy(save_Weights, Weight_List, save_tw_size * sizeof(DBL));
  449.  
  450.     save_Textures = (TEXTURE **)POV_MALLOC(save_tw_size * sizeof(TEXTURE *), "Weight list stack");
  451.  
  452.     memcpy(save_Textures, Texture_List, save_tw_size * sizeof(TEXTURE *));
  453.   }
  454.  
  455.   /* Get texture list and weights. */
  456.  
  457.   Texture_Count = create_texture_list (Ray_Intersection);
  458.  
  459.   /*
  460.    * Now, we perform the lighting calculations by stepping through
  461.    * the list of textures and summing the weighted color.
  462.    */
  463.  
  464.   for (i = 0; i < Texture_Count; i++)
  465.   {
  466.     /* If contribution of this texture is neglectable skip ahead. */
  467.  
  468.     if (Weight_List[i] < BLACK_LEVEL)
  469.     {
  470.       continue;
  471.     }
  472.  
  473.     Texture = Texture_List[i];
  474.  
  475.     do_texture_map(C1, Texture, IPoint, Raw_Normal, Ray, Weight, Ray_Intersection, FALSE);
  476.  
  477.     Colour[RED]   += Weight_List[i] * C1[RED];
  478.     Colour[GREEN] += Weight_List[i] * C1[GREEN];
  479.     Colour[BLUE]  += Weight_List[i] * C1[BLUE];
  480.  
  481.     /* Use transmittance value for alpha channel support. [DB] */
  482.  
  483. /*
  484.     Colour[TRANSM]  += Weight_List[i] * C1[TRANSM];
  485. */
  486.     Colour[TRANSM] *= C1[TRANSM];
  487.   }
  488.  
  489.   /* Restore the light list to its original form */
  490.  
  491.   if (savelights_size > 0)
  492.   {
  493.     memcpy(Light_List, savelights, savelights_size);
  494.  
  495.     POV_FREE(savelights);
  496.   }
  497.  
  498.   /* Restore the weight and texture list. */
  499.  
  500.   if (save_tw_size > 0)
  501.   {
  502.     memcpy(Weight_List, save_Weights, save_tw_size * sizeof(DBL));
  503.     memcpy(Texture_List, save_Textures, save_tw_size * sizeof(TEXTURE *));
  504.  
  505.     POV_FREE(save_Weights);
  506.     POV_FREE(save_Textures);
  507.   }
  508. }
  509.  
  510.  
  511.  
  512. /*****************************************************************************
  513. *
  514. * FUNCTION
  515. *
  516. *   Test_Shadow
  517. *
  518. * INPUT
  519. *
  520. *   Light            - Light source
  521. *   P                - Point to test
  522. *
  523. * OUTPUT
  524. *
  525. *   Depth            - Distance to light source
  526. *   Light_Source_Ray - Light ray pointing towards the light source
  527. *   Eye_Ray          - Current viewing ray
  528. *   Colour           - Light color reaching point P
  529. *
  530. * RETURNS
  531. *
  532. *   int - TRUE if point lies in shadow
  533. *
  534. * AUTHOR
  535. *
  536. *   Dieter Bayer
  537. *
  538. * DESCRIPTION
  539. *
  540. *   Test if a given point is in shadow in respect to the given light source.
  541. *
  542. *   The viewing ray is used to initialize the ray containers of the
  543. *   light source ray.
  544. *
  545. * CHANGES
  546. *
  547. *   Nov 1994 : Creation.
  548. *
  549. ******************************************************************************/
  550.  
  551. int Test_Shadow(Light, Depth, Light_Source_Ray, Eye_Ray, P, Colour)
  552. LIGHT_SOURCE *Light;
  553. DBL *Depth;
  554. RAY *Light_Source_Ray, *Eye_Ray;
  555. VECTOR P;
  556. COLOUR Colour;
  557. {
  558.   do_light(Light, Depth, Light_Source_Ray, Eye_Ray, P, Colour);
  559.  
  560.   /*
  561.    * There's no need to test for shadows if no light
  562.    * is coming from the light source.
  563.    */
  564.  
  565.   if ((Colour[X] < BLACK_LEVEL) && (Colour[Y] < BLACK_LEVEL) && (Colour[Z] < BLACK_LEVEL))
  566.   {
  567.     return(TRUE);
  568.   }
  569.   else
  570.   {
  571.     /* Test for shadows. */
  572.  
  573.     if ((opts.Quality_Flags & Q_SHADOW) && (Light->Light_Type != FILL_LIGHT_SOURCE))
  574.     {
  575.       block_light_source(Light, *Depth, Light_Source_Ray, Eye_Ray, P, Colour);
  576.  
  577.       if ((Colour[X] < BLACK_LEVEL) && (Colour[Y] < BLACK_LEVEL) && (Colour[Z] < BLACK_LEVEL))
  578.       {
  579.         return(TRUE);
  580.       }
  581.     }
  582.   }
  583.  
  584.   return(FALSE);
  585. }
  586.  
  587.  
  588.  
  589. /*****************************************************************************
  590. *
  591. * FUNCTION
  592. *
  593. *   block_point_light_LBuffer
  594. *
  595. * INPUT
  596. *
  597. *   Light_Source       - Light source to test
  598. *
  599. * OUTPUT
  600. *
  601. *   Light_Source_Depth - (Remaining) distance to the light source
  602. *   Light_Source_Ray   - (Remaining) ray to the light source
  603. *   Colour             - Color reaching initial point from light source
  604. *
  605. * RETURNS
  606. *
  607. * AUTHOR
  608. *
  609. *   Dieter Bayer
  610. *
  611. * DESCRIPTION
  612. *
  613. *   Determine how much light from the given light source arrives at the
  614. *   given point (starting point of the light source ray). The light
  615. *   is blocked by solid objects and/or attenuated by translucent objects.
  616. *
  617. *   Note that both the distance to the light source and the light source
  618. *   ray are modified. Thus after a call to this function one knows
  619. *   how much distance remains to the light source and where the last
  620. *   intersection point with a translucent object was (starting point
  621. *   of light source ray after the call).
  622. *
  623. *   This function uses the light buffer to speed up shadow calculation.
  624. *
  625. * CHANGES
  626. *
  627. *   Jul 1994 : Creation.
  628. *
  629. ******************************************************************************/
  630.  
  631. static void block_point_light_LBuffer(Light_Source, Light_Source_Depth, Light_Source_Ray, Light_Colour)
  632. LIGHT_SOURCE *Light_Source;
  633. DBL *Light_Source_Depth;
  634. RAY *Light_Source_Ray;
  635. COLOUR Light_Colour;
  636. {
  637.   int Quit_Looking, Not_Found_Shadow, Cache_Me;
  638.   int u, v, axis;
  639.   DBL ax, ay, az;
  640.   DBL rdiv;
  641.   VECTOR V1;
  642.   OBJECT *Blocking_Object;
  643.   ISTACK *Local_Stack;
  644.   INTERSECTION *Local_Intersection, Bounded_Intersection;
  645.  
  646.   Local_Stack = open_istack();
  647.  
  648.   Quit_Looking = FALSE;
  649.  
  650.   /* First test the cached object (don't cache semi-transparent objects). */
  651.  
  652.   if (Light_Source->Shadow_Cached_Object != NULL)
  653.   {
  654.     Increase_Counter(stats[Shadow_Ray_Tests]);
  655.  
  656.     if (Ray_In_Bound(Light_Source_Ray, Light_Source->Shadow_Cached_Object->Bound))
  657.     {
  658.       if (All_Intersections(Light_Source->Shadow_Cached_Object, Light_Source_Ray, Local_Stack))
  659.       {
  660.         while ((Local_Intersection=pop_entry(Local_Stack)) != NULL)
  661.         {
  662.           if ((!Test_Flag(Local_Intersection->Object, NO_SHADOW_FLAG)) &&
  663.               (Local_Intersection->Depth < *Light_Source_Depth-SHADOW_TOLERANCE) &&
  664.               (Local_Intersection->Depth > SHADOW_TOLERANCE))
  665.           {
  666.             if (do_blocking(Local_Intersection, Light_Source_Ray, Light_Colour, Local_Stack))
  667.             {
  668.               Quit_Looking = TRUE;
  669.  
  670.               Increase_Counter(stats[Shadow_Cache_Hits]);
  671.  
  672.               break;
  673.             }
  674.           }
  675.         }
  676.       }
  677.     }
  678.  
  679.     /* Exit if the cached object was hit. */
  680.  
  681.     if (Quit_Looking)
  682.     {
  683.       close_istack(Local_Stack);
  684.  
  685.       return;
  686.     }
  687.   }
  688.  
  689.   /*
  690.    * Determine the side and the coordinates at which the ray
  691.    * pierces the cube enclosing the light source.
  692.    */
  693.  
  694.   V1[X] = -Light_Source_Ray->Direction[X];
  695.   V1[Y] = -Light_Source_Ray->Direction[Y];
  696.   V1[Z] = -Light_Source_Ray->Direction[Z];
  697.  
  698.   ax = fabs(V1[X]);
  699.   ay = fabs(V1[Y]);
  700.   az = fabs(V1[Z]);
  701.  
  702.   if ((ax>ay) && (ax>az))
  703.   {
  704.     if (V1[X]>0.0)
  705.     {
  706.       axis = XaxisP;
  707.     }
  708.     else
  709.     {
  710.       axis = XaxisM;
  711.     }
  712.     rdiv = (1.0 / ax);
  713.     u = (int)(MAX_BUFFER_ENTRY * V1[Y]*rdiv);
  714.     v = (int)(MAX_BUFFER_ENTRY * V1[Z]*rdiv);
  715. /*
  716.     u = (int)(MAX_BUFFER_ENTRY * V1[Y]/ax);
  717.     v = (int)(MAX_BUFFER_ENTRY * V1[Z]/ax);
  718. */
  719.   }
  720.   else
  721.   {
  722.     if (ay>az)
  723.     {
  724.       if (V1[Y]>0.0)
  725.       {
  726.         axis = YaxisP;
  727.       }
  728.       else
  729.       {
  730.         axis = YaxisM;
  731.       }
  732.       rdiv = (1.0 / ay);
  733.       u = (int)(MAX_BUFFER_ENTRY * V1[X]*rdiv);
  734.       v = (int)(MAX_BUFFER_ENTRY * V1[Z]*rdiv);
  735. /*
  736.       u = (int)(MAX_BUFFER_ENTRY * V1[X]/ay);
  737.       v = (int)(MAX_BUFFER_ENTRY * V1[Z]/ay);
  738. */
  739.     }
  740.     else
  741.     {
  742.       if (V1[Z]>0.0)
  743.       {
  744.         axis = ZaxisP;
  745.       }
  746.       else
  747.       {
  748.         axis = ZaxisM;
  749.       }
  750.       rdiv = (1.0 / az);
  751.       u = (int)(MAX_BUFFER_ENTRY * V1[X]*rdiv);
  752.       v = (int)(MAX_BUFFER_ENTRY * V1[Y]*rdiv);
  753. /*
  754.       u = (int)(MAX_BUFFER_ENTRY * V1[X]/az);
  755.       v = (int)(MAX_BUFFER_ENTRY * V1[Y]/az);
  756. */
  757.     }
  758.   }
  759.  
  760.   /* If there are no objects in the direction of the ray we can exit. */
  761.  
  762.   if (Light_Source->Light_Buffer[axis] == NULL)
  763.   {
  764.     close_istack(Local_Stack);
  765.  
  766.     return;
  767.   }
  768.  
  769.   /* Look for shadows. */
  770.  
  771.   Not_Found_Shadow = TRUE;
  772.  
  773.   Cache_Me = FALSE;
  774.  
  775.   while (!Quit_Looking)
  776.   {
  777.     Increase_Counter(stats[Shadow_Ray_Tests]);
  778.  
  779.     Bounded_Intersection.Depth = *Light_Source_Depth;
  780.  
  781.     if (Intersect_Light_Tree(Light_Source_Ray, Light_Source->Light_Buffer[axis], u, v, &Bounded_Intersection, &Blocking_Object))
  782.     {
  783.       if (Bounded_Intersection.Depth > *Light_Source_Depth)
  784.       {
  785.         /* Intersection was beyond the light. */
  786.  
  787.         break;
  788.       }
  789.  
  790.       if (!Test_Flag(Bounded_Intersection.Object, NO_SHADOW_FLAG))
  791.       {
  792.         if (Blocking_Object != Light_Source->Shadow_Cached_Object)
  793.         {
  794.           Increase_Counter(stats[Shadow_Rays_Succeeded]);
  795.  
  796.           filter_shadow_ray(&Bounded_Intersection, Light_Source_Ray, Light_Colour);
  797.  
  798.           if ((fabs(Light_Colour[RED])   < BLACK_LEVEL) &&
  799.               (fabs(Light_Colour[GREEN]) < BLACK_LEVEL) &&
  800.               (fabs(Light_Colour[BLUE])  < BLACK_LEVEL) &&
  801.               (Test_Flag(Blocking_Object, OPAQUE_FLAG)))
  802.           {
  803.             Cache_Me = Not_Found_Shadow;
  804.  
  805.             break; /* from while */
  806.           }
  807.         }
  808.       }
  809.  
  810.       /* Move the ray to the point of intersection, plus some */
  811.  
  812.       *Light_Source_Depth -= Bounded_Intersection.Depth;
  813.  
  814.       Assign_Vector(Light_Source_Ray->Initial, Bounded_Intersection.IPoint);
  815.  
  816.       Not_Found_Shadow = FALSE;
  817.     }
  818.     else
  819.     {
  820.       /* No intersections in the direction of the ray. */
  821.  
  822.       break;
  823.     }
  824.   }
  825.  
  826.   if (Cache_Me)
  827.   {
  828.     Light_Source->Shadow_Cached_Object = Blocking_Object;
  829.   }
  830.  
  831.   close_istack(Local_Stack);
  832. }
  833.  
  834.  
  835.  
  836. /*****************************************************************************
  837. *
  838. * FUNCTION
  839. *
  840. *   block_point_light
  841. *
  842. * INPUT
  843. *
  844. *   Light_Source       - Light source to test
  845. *   Eye_Ray            - Current viewing ray
  846. *
  847. * OUTPUT
  848. *
  849. *   Light_Source_Depth - (Remaining) distance to the light source
  850. *   Light_Source_Ray   - (Remaining) ray to the light source
  851. *   Colour             - Color reaching initial point from light source
  852. *
  853. * RETURNS
  854. *
  855. * AUTHOR
  856. *
  857. *   POV-Ray Team
  858. *
  859. * DESCRIPTION
  860. *
  861. *   See block_point_light_LBuffer for a description.
  862. *
  863. *   This function uses the hierarchical bounding box volume to
  864. *   speed up shadow testing.
  865. *
  866. * CHANGES
  867. *
  868. *   -
  869. *
  870. ******************************************************************************/
  871.  
  872. static void block_point_light (Light_Source, Light_Source_Depth, Light_Source_Ray, Light_Colour)
  873. LIGHT_SOURCE *Light_Source;
  874. DBL *Light_Source_Depth;
  875. RAY *Light_Source_Ray;
  876. COLOUR Light_Colour;
  877. {
  878.   OBJECT *Blocking_Object;
  879.   int Quit_Looking, Not_Found_Shadow, Cache_Me, Maybe_Found;
  880.   INTERSECTION *Local_Intersection, Bounded_Intersection, Temp_Intersection;
  881.   ISTACK *Local_Stack;
  882.  
  883.   Local_Stack = open_istack ();
  884.  
  885.   Quit_Looking = FALSE;
  886.  
  887.   /* First test the cached object (don't cache semi-transparent objects). */
  888.  
  889.   if (Light_Source->Shadow_Cached_Object != NULL)
  890.   {
  891.     Increase_Counter(stats[Shadow_Ray_Tests]);
  892.  
  893.     if (Ray_In_Bound(Light_Source_Ray, Light_Source->Shadow_Cached_Object->Bound))
  894.     {
  895.       if (All_Intersections(Light_Source->Shadow_Cached_Object, Light_Source_Ray, Local_Stack))
  896.       {
  897.         while ((Local_Intersection = pop_entry(Local_Stack)) != NULL)
  898.         {
  899.           if ((!Test_Flag(Local_Intersection->Object, NO_SHADOW_FLAG)) &&
  900.               (Local_Intersection->Depth < *Light_Source_Depth-SHADOW_TOLERANCE) &&
  901.               (Local_Intersection->Depth > SHADOW_TOLERANCE))
  902.           {
  903.             if (do_blocking(Local_Intersection, Light_Source_Ray, Light_Colour, Local_Stack))
  904.             {
  905.               Quit_Looking = TRUE;
  906.  
  907.               Increase_Counter(stats[Shadow_Cache_Hits]);
  908.  
  909.               break;
  910.             }
  911.           }
  912.         }
  913.       }
  914.     }
  915.  
  916.     if (Quit_Looking)
  917.     {
  918.       close_istack (Local_Stack);
  919.  
  920.       return;
  921.     }
  922.   }
  923.  
  924.   /* Look for shadows. */
  925.  
  926.   Not_Found_Shadow = TRUE;
  927.  
  928.   Cache_Me = FALSE;
  929.  
  930.   if (!opts.Use_Slabs)
  931.   {
  932.     while (!Quit_Looking)
  933.     {
  934.       /* Use brute force method to get shadows. */
  935.  
  936.       Maybe_Found = FALSE;
  937.  
  938.       Bounded_Intersection.Depth = *Light_Source_Depth;
  939.  
  940.       for (Blocking_Object = Frame.Objects; Blocking_Object != NULL; Blocking_Object = Blocking_Object->Sibling)
  941.       {
  942.         if (Blocking_Object != Light_Source->Shadow_Cached_Object)
  943.         {
  944.           if (!Test_Flag(Blocking_Object, NO_SHADOW_FLAG))
  945.           {
  946.             Increase_Counter(stats[Shadow_Ray_Tests]);
  947.  
  948.             if (Intersection(&Temp_Intersection, Blocking_Object, Light_Source_Ray))
  949.             {
  950.               if (Temp_Intersection.Depth < Bounded_Intersection.Depth)
  951.               {
  952.                 Maybe_Found = TRUE;
  953.  
  954.                 Bounded_Intersection = Temp_Intersection;
  955.               }
  956.             }
  957.           }
  958.         }
  959.       }
  960.  
  961.       if (Maybe_Found)
  962.       {
  963.         Increase_Counter(stats[Shadow_Rays_Succeeded]);
  964.  
  965.         filter_shadow_ray(&Bounded_Intersection, Light_Source_Ray, Light_Colour);
  966.  
  967.         if ((fabs(Light_Colour[RED])   < BLACK_LEVEL) &&
  968.             (fabs(Light_Colour[GREEN]) < BLACK_LEVEL) &&
  969.             (fabs(Light_Colour[BLUE])  < BLACK_LEVEL) &&
  970.             (Test_Flag(Bounded_Intersection.Object, OPAQUE_FLAG)))
  971.         {
  972.           Cache_Me = Not_Found_Shadow;
  973.  
  974.           break;
  975.         }
  976.  
  977.         /* Move the ray to the point of intersection, plus some */
  978.  
  979.         *Light_Source_Depth -= Bounded_Intersection.Depth;
  980.  
  981.         Assign_Vector(Light_Source_Ray->Initial, Bounded_Intersection.IPoint);
  982.  
  983.         Not_Found_Shadow = FALSE;
  984.       }
  985.       else
  986.       {
  987.         /* No intersections in the direction of the ray. */
  988.  
  989.         break;
  990.       }
  991.     }
  992.   }
  993.   else
  994.   {
  995.     /* Use bounding slabs to look for shadows. */
  996.  
  997.     while (!Quit_Looking)
  998.     {
  999.       Increase_Counter(stats[Shadow_Ray_Tests]);
  1000.  
  1001.       Bounded_Intersection.Depth = *Light_Source_Depth;
  1002.  
  1003.       if (Intersect_BBox_Tree(Root_Object, Light_Source_Ray, &Bounded_Intersection, &Blocking_Object))
  1004.       {
  1005.         if (Bounded_Intersection.Depth > *Light_Source_Depth)
  1006.         {
  1007.           /* Intersection was beyond the light. */
  1008.  
  1009.           break;
  1010.         }
  1011.  
  1012.         if (!Test_Flag(Bounded_Intersection.Object, NO_SHADOW_FLAG))
  1013.         {
  1014.           if (Blocking_Object != Light_Source->Shadow_Cached_Object)
  1015.           {
  1016.             Increase_Counter(stats[Shadow_Rays_Succeeded]);
  1017.  
  1018.             filter_shadow_ray(&Bounded_Intersection, Light_Source_Ray, Light_Colour);
  1019.  
  1020.             if ((fabs(Light_Colour[RED])   < BLACK_LEVEL) &&
  1021.                 (fabs(Light_Colour[GREEN]) < BLACK_LEVEL) &&
  1022.                 (fabs(Light_Colour[BLUE])  < BLACK_LEVEL) &&
  1023.                 (Test_Flag(Blocking_Object, OPAQUE_FLAG)))
  1024.             {
  1025.               Cache_Me = Not_Found_Shadow;
  1026.  
  1027.               break; /* from while */
  1028.             }
  1029.           }
  1030.         }
  1031.  
  1032.         /* Move the ray to the point of intersection, plus some */
  1033.  
  1034.         *Light_Source_Depth -= Bounded_Intersection.Depth;
  1035.  
  1036.         Assign_Vector(Light_Source_Ray->Initial, Bounded_Intersection.IPoint);
  1037.  
  1038.         Not_Found_Shadow = FALSE;
  1039.       }
  1040.       else
  1041.       {
  1042.         /* No intersections in the direction of the ray */
  1043.  
  1044.         break;
  1045.       }
  1046.     }
  1047.   }
  1048.  
  1049.   if (Cache_Me)
  1050.   {
  1051.     Light_Source->Shadow_Cached_Object = Blocking_Object;
  1052.   }
  1053.  
  1054.   close_istack (Local_Stack);
  1055. }
  1056.  
  1057.  
  1058.  
  1059. /*****************************************************************************
  1060. *
  1061. * FUNCTION
  1062. *
  1063. *   block_area_light
  1064. *
  1065. * INPUT
  1066. *
  1067. *   Light_Source       - Light source to test
  1068. *   IPoint             -
  1069. *   u1, v1, u2, v2     -
  1070. *   Level              -
  1071. *
  1072. * OUTPUT
  1073. *
  1074. *   Light_Source_Depth - (Remaining) distance to the light source
  1075. *   Light_Source_Ray   - (Remaining) ray to the light source
  1076. *   Light_Colour       - Color reaching initial point from light source
  1077. *
  1078. * RETURNS
  1079. *
  1080. * AUTHOR
  1081. *
  1082. *   POV-Ray Team
  1083. *
  1084. * DESCRIPTION
  1085. *
  1086. *   Get shadow for given area light source by recursively sampling
  1087. *   on the light source area.
  1088. *
  1089. *   The viewing ray is used to initialize the ray containers of the
  1090. *   light source ray.
  1091. *
  1092. * CHANGES
  1093. *
  1094. *   -
  1095. *
  1096. ******************************************************************************/
  1097.  
  1098. static void block_area_light (Light_Source, Light_Source_Depth,
  1099.   Light_Source_Ray, Eye_Ray, IPoint, Light_Colour, u1, v1, u2, v2, Level)
  1100. LIGHT_SOURCE *Light_Source;
  1101. DBL *Light_Source_Depth;
  1102. RAY *Light_Source_Ray, *Eye_Ray;
  1103. VECTOR IPoint;
  1104. COLOUR Light_Colour;
  1105. int u1, v1, u2, v2, Level;
  1106. {
  1107.   COLOUR Sample_Colour[4], Dummy_Colour;
  1108.   VECTOR Center_Save, NewAxis1, NewAxis2;
  1109.   int i, j, u, v, New_u1, New_v1, New_u2, New_v2;
  1110.  
  1111.   DBL Jitter_u, Jitter_v, ScaleFactor;
  1112.  
  1113.   /* First call, initialize */
  1114.  
  1115.   if ((u1 == 0) && (v1 == 0) && (u2 == 0) && (v2 == 0))
  1116.   {
  1117.     /* Flag uncalculated points with a negative value for Red */
  1118.  
  1119.     for (i = 0; i < Light_Source->Area_Size1; i++)
  1120.     {
  1121.       for (j = 0; j < Light_Source->Area_Size2; j++)
  1122.       {
  1123.         Light_Source->Light_Grid[i][j][RED] = -1.0;
  1124.       }
  1125.     }
  1126.  
  1127.     u1 = 0;
  1128.     v1 = 0;
  1129.     u2 = Light_Source->Area_Size1 - 1;
  1130.     v2 = Light_Source->Area_Size2 - 1;
  1131.   }
  1132.  
  1133.   /* Save the light source center since we'll be fiddling with it */
  1134.  
  1135.   Assign_Vector(Center_Save,Light_Source->Center);
  1136.  
  1137.   /* Sample the four corners of the region */
  1138.  
  1139.   for (i = 0; i < 4; i++)
  1140.   {
  1141.     switch (i)
  1142.     {
  1143.       case 0: u = u1; v = v1; break;
  1144.       case 1: u = u2; v = v1; break;
  1145.       case 2: u = u1; v = v2; break;
  1146.       case 3: u = u2; v = v2; break;
  1147.       default: u = v = 0;  /* Should never happen! */
  1148.     }
  1149.  
  1150.     if (Light_Source->Light_Grid[u][v][RED] >= 0.0)
  1151.     {
  1152.       /* We've already calculated this point, reuse it */
  1153.  
  1154.       Assign_Colour(Sample_Colour[i],Light_Source->Light_Grid[u][v]);
  1155.     }
  1156.     else
  1157.     {
  1158.       Jitter_u = (DBL)u;
  1159.       Jitter_v = (DBL)v;
  1160.  
  1161.       if (Light_Source->Jitter)
  1162.       {
  1163.         Jitter_u += FRAND() - 0.5;
  1164.         Jitter_v += FRAND() - 0.5;
  1165.       }
  1166.  
  1167.       if (Light_Source->Area_Size1 > 1)
  1168.       {
  1169.         ScaleFactor = Jitter_u/(DBL)(Light_Source->Area_Size1 - 1) - 0.5;
  1170.  
  1171.         VScale (NewAxis1, Light_Source->Axis1, ScaleFactor)
  1172.       }
  1173.       else
  1174.       {
  1175.         Make_Vector(NewAxis1, 0.0, 0.0, 0.0);
  1176.       }
  1177.  
  1178.       if (Light_Source->Area_Size2 > 1)
  1179.       {
  1180.         ScaleFactor = Jitter_v/(DBL)(Light_Source->Area_Size2 - 1) - 0.5;
  1181.  
  1182.         VScale (NewAxis2, Light_Source->Axis2, ScaleFactor)
  1183.       }
  1184.       else
  1185.       {
  1186.         Make_Vector(NewAxis2, 0.0, 0.0, 0.0);
  1187.       }
  1188.  
  1189.       Assign_Vector(Light_Source->Center, Center_Save);
  1190.  
  1191.       VAddEq(Light_Source->Center, NewAxis1);
  1192.       VAddEq(Light_Source->Center, NewAxis2);
  1193.  
  1194.       /* Recalculate the light source ray but not the colour */
  1195.  
  1196.       do_light(Light_Source, Light_Source_Depth, Light_Source_Ray, Eye_Ray, IPoint, Dummy_Colour);
  1197.  
  1198.       Assign_Colour(Sample_Colour[i], Light_Colour);
  1199.  
  1200.       block_point_light(Light_Source, Light_Source_Depth, Light_Source_Ray, Sample_Colour[i]);
  1201.  
  1202.       Assign_Colour(Light_Source->Light_Grid[u][v], Sample_Colour[i]);
  1203.     }
  1204.   }
  1205.  
  1206.   Assign_Vector(Light_Source->Center,Center_Save);
  1207.  
  1208.   if ((u2 - u1 > 1) || (v2 - v1 > 1))
  1209.   {
  1210.     if ((Level < Light_Source->Adaptive_Level) ||
  1211.         (Colour_Distance(Sample_Colour[0], Sample_Colour[1]) > 0.1) ||
  1212.         (Colour_Distance(Sample_Colour[1], Sample_Colour[3]) > 0.1) ||
  1213.         (Colour_Distance(Sample_Colour[3], Sample_Colour[2]) > 0.1) ||
  1214.         (Colour_Distance(Sample_Colour[2], Sample_Colour[0]) > 0.1))
  1215.     {
  1216.       for (i = 0; i < 4; i++)
  1217.       {
  1218.         switch (i)
  1219.         {
  1220.           case 0:
  1221.  
  1222.             New_u1 = u1;
  1223.             New_v1 = v1;
  1224.             New_u2 = (int)floor ((u1 + u2)/2.0);
  1225.             New_v2 = (int)floor ((v1 + v2)/2.0);
  1226.  
  1227.             break;
  1228.  
  1229.           case 1:
  1230.  
  1231.             New_u1 = (int)ceil  ((u1 + u2)/2.0);
  1232.             New_v1 = v1;
  1233.             New_u2 = u2;
  1234.             New_v2 = (int)floor ((v1 + v2)/2.0);
  1235.  
  1236.             break;
  1237.  
  1238.           case 2:
  1239.  
  1240.             New_u1 = u1;
  1241.             New_v1 = (int)ceil  ((v1 + v2)/2.0);
  1242.             New_u2 = (int)floor ((u1 + u2)/2.0);
  1243.             New_v2 = v2;
  1244.  
  1245.             break;
  1246.  
  1247.           case 3:
  1248.  
  1249.             New_u1 = (int)ceil ((u1 + u2)/2.0);
  1250.             New_v1 = (int)ceil ((v1 + v2)/2.0);
  1251.             New_u2 = u2;
  1252.             New_v2 = v2;
  1253.  
  1254.             break;
  1255.  
  1256.           default:  /* Should never happen! */
  1257.  
  1258.             New_u1 = New_u2 = New_v1 = New_v2 = 0;
  1259.         }
  1260.  
  1261.         /* Recalculate the light source ray but not the colour */
  1262.  
  1263.         do_light(Light_Source, Light_Source_Depth, Light_Source_Ray, Eye_Ray, IPoint, Dummy_Colour);
  1264.  
  1265.         Assign_Colour(Sample_Colour[i],Light_Colour);
  1266.  
  1267.         block_area_light (Light_Source, Light_Source_Depth, Light_Source_Ray, Eye_Ray,
  1268.           IPoint, Sample_Colour[i], New_u1, New_v1, New_u2, New_v2, Level+1);
  1269.       }
  1270.     }
  1271.   }
  1272.  
  1273.   /* Add up the light contributions */
  1274.  
  1275.   Make_Colour (Light_Colour, 0.0, 0.0, 0.0);
  1276.  
  1277.   for (i = 0; i < 4; i++)
  1278.   {
  1279.     Scale_Colour (Sample_Colour[i], Sample_Colour[i], 0.25);
  1280.  
  1281.     Add_Colour (Light_Colour, Light_Colour, Sample_Colour[i]);
  1282.   }
  1283. }
  1284.  
  1285.  
  1286.  
  1287. /*****************************************************************************
  1288. *
  1289. * FUNCTION
  1290. *
  1291. *   do_light
  1292. *
  1293. * INPUT
  1294. *
  1295. *   Light_Source       - Light source
  1296. *   Light_Source_Depth - Distance from surface to light source
  1297. *   Light_Source_Ray   - Ray from surface to light source
  1298. *   Eye_Ray            - Current viewing ray
  1299. *   IPoint             - Intersection point in surface
  1300. *   Colour             - Light's colour
  1301. *
  1302. * OUTPUT
  1303. *
  1304. *   Light_Source_Depth, Light_Source_Ray, Colour
  1305. *
  1306. * RETURNS
  1307. *
  1308. * AUTHOR
  1309. *
  1310. *   POV-Ray Team
  1311. *
  1312. * DESCRIPTION
  1313. *
  1314. *   The viewing ray is used to initialize the ray containers of the
  1315. *   light source ray.
  1316. *
  1317. * CHANGES
  1318. *
  1319. *   -
  1320. *
  1321. ******************************************************************************/
  1322.  
  1323. static void do_light(Light_Source, Light_Source_Depth, Light_Source_Ray, Eye_Ray, IPoint, Light_Colour)
  1324. LIGHT_SOURCE *Light_Source;
  1325. DBL *Light_Source_Depth;
  1326. RAY *Light_Source_Ray, *Eye_Ray;
  1327. VECTOR IPoint;
  1328. COLOUR Light_Colour;
  1329. {
  1330.   DBL Attenuation;
  1331.  
  1332.   /* Get the light source colour. */
  1333.  
  1334.   Assign_Colour(Light_Colour, Light_Source->Colour);
  1335.  
  1336.   /*
  1337.    * Get the light ray starting at the intersection point and pointing
  1338.    * towards the light source.
  1339.    */
  1340.  
  1341.   Assign_Vector(Light_Source_Ray->Initial, IPoint);
  1342.  
  1343.   VSub(Light_Source_Ray->Direction,Light_Source->Center, IPoint);
  1344.  
  1345.   VLength(*Light_Source_Depth, Light_Source_Ray->Direction);
  1346.  
  1347.   VInverseScaleEq(Light_Source_Ray->Direction, *Light_Source_Depth);
  1348.  
  1349.   /* Attenuate light source color. */
  1350.  
  1351.   Attenuation = Attenuate_Light(Light_Source, Light_Source_Ray, *Light_Source_Depth);
  1352.  
  1353.   /* Now scale the color by the attenuation */
  1354.  
  1355.   VScaleEq(Light_Colour, Attenuation);
  1356.  
  1357.   /* Init ray containers. */
  1358.  
  1359.   Initialize_Ray_Containers(Light_Source_Ray);
  1360.  
  1361.   Copy_Ray_Containers(Light_Source_Ray, Eye_Ray);
  1362. }
  1363.  
  1364.  
  1365.  
  1366. /*****************************************************************************
  1367. *
  1368. * FUNCTION
  1369. *
  1370. *   do_diffuse
  1371. *
  1372. * INPUT
  1373. *
  1374. * OUTPUT
  1375. *
  1376. * RETURNS
  1377. *
  1378. * AUTHOR
  1379. *
  1380. *   POV-Ray Team
  1381. *
  1382. * DESCRIPTION
  1383. *
  1384. *   Calculate the diffuse color component I_d given by:
  1385. *
  1386. *     I_d = a * d * I * C * (N . L) ^ b
  1387. *
  1388. *   where d : surface's diffuse reflection coefficient
  1389. *         b : surface's brilliance
  1390. *         C : surface's color
  1391. *         N : surface's normal vector
  1392. *         L : light vector (pointing at the light)
  1393. *         I : intensity of the incoming light
  1394. *         a : attenuation factor
  1395. *
  1396. * CHANGES
  1397. *
  1398. *   -
  1399. *
  1400. ******************************************************************************/
  1401.  
  1402. static void do_diffuse(Finish, Light_Source_Ray, Layer_Normal, Colour, Light_Colour, Layer_Pigment_Colour, Attenuation)
  1403. FINISH *Finish;
  1404. RAY *Light_Source_Ray;
  1405. VECTOR Layer_Normal;
  1406. COLOUR Colour, Light_Colour, Layer_Pigment_Colour;
  1407. DBL Attenuation;
  1408. {
  1409.   DBL Cos_Angle_Of_Incidence, Intensity;
  1410.  
  1411.   VDot(Cos_Angle_Of_Incidence, Layer_Normal, Light_Source_Ray->Direction);
  1412.  
  1413.   /* Brilliance is likely to be 1.0 (default value) */
  1414.  
  1415.   if (Finish->Brilliance != 1.0)
  1416.   {
  1417.     Intensity = pow(fabs(Cos_Angle_Of_Incidence), Finish->Brilliance);
  1418.   }
  1419.   else
  1420.   {
  1421.     Intensity = fabs(Cos_Angle_Of_Incidence);
  1422.   }
  1423.  
  1424.   Intensity *= Finish->Diffuse * Attenuation;
  1425.  
  1426.   if (Finish->Crand > 0.0)
  1427.   {
  1428.     Intensity -= FRAND() * Finish->Crand;
  1429.   }
  1430.  
  1431.   Colour[RED]   += Intensity * Layer_Pigment_Colour[RED]   * Light_Colour[RED];
  1432.   Colour[GREEN] += Intensity * Layer_Pigment_Colour[GREEN] * Light_Colour[GREEN];
  1433.   Colour[BLUE]  += Intensity * Layer_Pigment_Colour[BLUE]  * Light_Colour[BLUE];
  1434. }
  1435.  
  1436.  
  1437.  
  1438. /*****************************************************************************
  1439. *
  1440. * FUNCTION
  1441. *
  1442. *   do_irid
  1443. *
  1444. * INPUT
  1445. *
  1446. * OUTPUT
  1447. *
  1448. * RETURNS
  1449. *
  1450. * AUTHOR
  1451. *
  1452. *   Dan Farmer
  1453. *
  1454. * DESCRIPTION
  1455. *
  1456. *   IRIDESCENCE:
  1457. *   -----------
  1458. *   Programmed by Dan Farmer.
  1459. *
  1460. *   Based on Chapter 10.2.4 of Three-Dimensional Computer Graphics
  1461. *   by Alan Watt.
  1462. *
  1463. *   Modulates the diffuse coefficients as a function of wavelength, the angle
  1464. *   between the light direction vector, and the surface normal.  It models
  1465. *   thin-film interference, as in a soap bubble or oilslick.
  1466. *
  1467. *   Wavelength at which cancellation offurs is a function of the refractive
  1468. *   index of the film, its thickness, and the angle of incidence of the
  1469. *   incoming light.  In this implementation, IOR is kept constant, while the
  1470. *   thickness of the film is specified, as well as being modulated with a
  1471. *   turbulence function.
  1472. *
  1473. * CHANGES
  1474. *
  1475. *   -
  1476. *
  1477. ******************************************************************************/
  1478.  
  1479. static void do_irid(Finish, Light_Source_Ray, Layer_Normal, IPoint, Colour)
  1480. FINISH *Finish;
  1481. RAY *Light_Source_Ray;
  1482. VECTOR Layer_Normal, IPoint;
  1483. COLOUR Colour;
  1484. {
  1485.   DBL rwl, gwl, bwl;
  1486.   DBL Cos_Angle_Of_Incidence, interference;
  1487.   DBL film_thickness;
  1488.   DBL noise, intensity;
  1489.   TURB Turb;
  1490.  
  1491.   film_thickness = Finish->Irid_Film_Thickness;
  1492.  
  1493.   if (Finish->Irid_Turb != 0)
  1494.   {
  1495.     /* Uses hardcoded octaves, lambda, omega */
  1496.     Turb.Omega=0.5;
  1497.     Turb.Lambda=2.0;
  1498.     Turb.Octaves=5;
  1499.  
  1500.     noise = Turbulence(IPoint, &Turb) * Finish->Irid_Turb;
  1501.  
  1502.     film_thickness *= noise;
  1503.   }
  1504.  
  1505.   /*
  1506.    * Approximate dominant wavelengths of primary hues.
  1507.    * Source: 3D Computer Graphics by John Vince (Addison Wesely)
  1508.    * These are initialized in parse.c (Parse_Frame)
  1509.    * and are user-adjustable with the irid_wavelength keyword.
  1510.    * Red = 700 nm  Grn = 520 nm Blu = 480 nm
  1511.    * Divided by 100 gives: rwl = 0.70;  gwl = 0.52;  bwl = 0.48;
  1512.    *
  1513.    * However... I originally "guessed" at the values and came up with
  1514.    * the following, which I'm using as the defaults, since it seems
  1515.    * to work better:  rwl = 0.25;  gwl = 0.18;  bwl = 0.14;
  1516.    */
  1517.  
  1518.   /* Could avoid these assignments if we want to */
  1519.  
  1520.   rwl = Frame.Irid_Wavelengths[RED];
  1521.   gwl = Frame.Irid_Wavelengths[GREEN];
  1522.   bwl = Frame.Irid_Wavelengths[BLUE];
  1523.  
  1524.   /* NOTE: Shouldn't we compute Cos_Angle_Of_Incidence just once? */
  1525.  
  1526.   VDot(Cos_Angle_Of_Incidence, Layer_Normal, Light_Source_Ray->Direction);
  1527.  
  1528.   /* Calculate phase offset. */
  1529.  
  1530.   interference = 4.0 * M_PI * film_thickness * Cos_Angle_Of_Incidence;
  1531.  
  1532.   intensity = Cos_Angle_Of_Incidence * Finish->Irid;
  1533.  
  1534.   /* Modify color by phase offset for each wavelength. */
  1535.  
  1536.   Colour[RED]  += Finish->Irid * (intensity * (1.0 - 0.5 * cos(interference/rwl)));
  1537.   Colour[GREEN]+= Finish->Irid * (intensity * (1.0 - 0.5 * cos(interference/gwl)));
  1538.   Colour[BLUE] += Finish->Irid * (intensity * (1.0 - 0.5 * cos(interference/bwl)));
  1539. }
  1540.  
  1541.  
  1542.  
  1543. /*****************************************************************************
  1544. *
  1545. * FUNCTION
  1546. *
  1547. *   do_phong
  1548. *
  1549. * INPUT
  1550. *
  1551. * OUTPUT
  1552. *
  1553. * RETURNS
  1554. *
  1555. * AUTHOR
  1556. *
  1557. *   POV-Ray Team
  1558. *
  1559. * DESCRIPTION
  1560. *
  1561. *   Calculate the phong reflected color component I_p given by:
  1562. *
  1563. *     I_p = p * C * (R . L) ^ s
  1564. *
  1565. *   where p : surface's phong reflection coefficient
  1566. *         s : surface's phong size
  1567. *         C : surface's color/light color depending on the metallic flag
  1568. *         R : reflection vector
  1569. *         L : light vector (pointing at the light)
  1570. *
  1571. *   The reflection vector is calculated from the surface normal and
  1572. *   the viewing vector (looking at the surface point):
  1573. *
  1574. *     R = -2 * (V . N) * N + V, with R . R = 1
  1575. *
  1576. * CHANGES
  1577. *
  1578. *   Sep 1994 : Added improved color calculation for metallic surfaces. [DB]
  1579. *
  1580. ******************************************************************************/
  1581.  
  1582. static void do_phong(Finish, Light_Source_Ray, Eye, Layer_Normal, Colour, Light_Colour, Layer_Pigment_Colour)
  1583. FINISH *Finish;
  1584. RAY *Light_Source_Ray;
  1585. VECTOR Layer_Normal, Eye;
  1586. COLOUR Colour, Light_Colour, Layer_Pigment_Colour;
  1587. {
  1588.   DBL Cos_Angle_Of_Incidence, Intensity;
  1589.   VECTOR Reflect_Direction;
  1590.   DBL NdotL, x, F;
  1591.   COLOUR Cs;
  1592.  
  1593.   VDot(Cos_Angle_Of_Incidence, Eye, Layer_Normal);
  1594.  
  1595.   Cos_Angle_Of_Incidence *= -2.0;
  1596.  
  1597.   VLinComb2(Reflect_Direction, 1.0, Eye, Cos_Angle_Of_Incidence, Layer_Normal);
  1598.  
  1599.   VDot(Cos_Angle_Of_Incidence, Reflect_Direction, Light_Source_Ray->Direction);
  1600.  
  1601.   if (Cos_Angle_Of_Incidence > 0.0)
  1602.   {
  1603.     Intensity = Finish->Phong * pow(Cos_Angle_Of_Incidence, Finish->Phong_Size);
  1604.  
  1605.     if (Finish->Metallic > 0.0)
  1606.     {
  1607.       /*
  1608.        * Calculate the reflected color by interpolating between
  1609.        * the light source color and the surface color according
  1610.        * to the (empirical) Fresnel reflectivity function. [DB 9/94]
  1611.        */
  1612.  
  1613.       VDot(NdotL, Layer_Normal, Light_Source_Ray->Direction);
  1614.  
  1615.       x = 2.0 * fabs(acos(NdotL)) / M_PI;
  1616.  
  1617.       F = 0.014567225 / Sqr(x - 1.12) - 0.011612903;
  1618.  
  1619.       Cs[RED]   = Light_Colour[RED]   * (1.0 + Finish->Metallic * (1.0 - F) * (Layer_Pigment_Colour[RED]   - 1.0));
  1620.       Cs[GREEN] = Light_Colour[GREEN] * (1.0 + Finish->Metallic * (1.0 - F) * (Layer_Pigment_Colour[GREEN] - 1.0));
  1621.       Cs[BLUE]  = Light_Colour[BLUE]  * (1.0 + Finish->Metallic * (1.0 - F) * (Layer_Pigment_Colour[BLUE]  - 1.0));
  1622.  
  1623.       VAddScaledEq(Colour, Intensity, Cs);
  1624.     }
  1625.     else
  1626.     {
  1627.       Colour[RED]   += Intensity * Light_Colour[RED];
  1628.       Colour[GREEN] += Intensity * Light_Colour[GREEN];
  1629.       Colour[BLUE]  += Intensity * Light_Colour[BLUE];
  1630.     }
  1631.   }
  1632. }
  1633.  
  1634.  
  1635.  
  1636. /*****************************************************************************
  1637. *
  1638. * FUNCTION
  1639. *
  1640. *   do_specular
  1641. *
  1642. * INPUT
  1643. *
  1644. * OUTPUT
  1645. *
  1646. * INPUT
  1647. *
  1648. * OUTPUT
  1649. *
  1650. * RETURNS
  1651. *
  1652. * AUTHOR
  1653. *
  1654. *   POV-Ray Team
  1655. *
  1656. * DESCRIPTION
  1657. *
  1658. *   Calculate the specular reflected color component I_s given by:
  1659. *
  1660. *     I_s = s * C * (H . N) ^ (1 / r)
  1661. *
  1662. *   where s : surface's specular reflection coefficient
  1663. *         r : surface's roughness
  1664. *         C : surface's color/light color depending on the metallic flag
  1665. *         N : surface's normal
  1666. *         H : bisection vector between V and L
  1667. *
  1668. *   The bisecting vector H is calculated by
  1669. *
  1670. *     H = (L - V) / sqrt((L - V).(L - V))
  1671. *
  1672. * CHANGES
  1673. *
  1674. *   Sep 1994 : Added improved color calculation for metallic surfaces. [DB]
  1675. *
  1676. ******************************************************************************/
  1677.  
  1678. static void do_specular(Finish, Light_Source_Ray, REye, Layer_Normal, Colour, Light_Colour, Layer_Pigment_Colour)
  1679. FINISH *Finish;
  1680. RAY *Light_Source_Ray;
  1681. VECTOR Layer_Normal, REye;
  1682. COLOUR Colour, Light_Colour, Layer_Pigment_Colour;
  1683. {
  1684.   DBL Cos_Angle_Of_Incidence, Intensity, Halfway_Length;
  1685.   VECTOR Halfway;
  1686.   DBL NdotL, x, F;
  1687.   COLOUR Cs;
  1688.  
  1689.   VHalf(Halfway, REye, Light_Source_Ray->Direction);
  1690.  
  1691.   VLength(Halfway_Length, Halfway);
  1692.  
  1693.   if (Halfway_Length > 0.0)
  1694.   {
  1695.     VDot(Cos_Angle_Of_Incidence, Halfway, Layer_Normal);
  1696.  
  1697.     Cos_Angle_Of_Incidence /= Halfway_Length;
  1698.  
  1699.     if (Cos_Angle_Of_Incidence > 0.0)
  1700.     {
  1701.       Intensity = Finish->Specular * pow(Cos_Angle_Of_Incidence, Finish->Roughness);
  1702.  
  1703.       if (Finish->Metallic > 0.0)
  1704.       {
  1705.         /*
  1706.          * Calculate the reflected color by interpolating between
  1707.          * the light source color and the surface color according
  1708.          * to the (empirical) Fresnel reflectivity function. [DB 9/94]
  1709.          */
  1710.  
  1711.         VDot(NdotL, Layer_Normal, Light_Source_Ray->Direction);
  1712.  
  1713.         x = 2.0 * fabs(acos(NdotL)) / M_PI;
  1714.  
  1715.         F = 0.014567225 / Sqr(x - 1.12) - 0.011612903;
  1716.  
  1717.         Cs[RED]   = Light_Colour[RED]   * (1.0 + Finish->Metallic * (1.0 - F) * (Layer_Pigment_Colour[RED]   - 1.0));
  1718.         Cs[GREEN] = Light_Colour[GREEN] * (1.0 + Finish->Metallic * (1.0 - F) * (Layer_Pigment_Colour[GREEN] - 1.0));
  1719.         Cs[BLUE]  = Light_Colour[BLUE]  * (1.0 + Finish->Metallic * (1.0 - F) * (Layer_Pigment_Colour[BLUE]  - 1.0));
  1720.  
  1721.         VAddScaledEq(Colour, Intensity, Cs);
  1722.       }
  1723.       else
  1724.       {
  1725.         Colour[RED]   += Intensity * Light_Colour[RED];
  1726.         Colour[GREEN] += Intensity * Light_Colour[GREEN];
  1727.         Colour[BLUE]  += Intensity * Light_Colour[BLUE];
  1728.       }
  1729.     }
  1730.   }
  1731. }
  1732.  
  1733.  
  1734.  
  1735. /*****************************************************************************
  1736. *
  1737. * FUNCTION
  1738. *
  1739. *   Diffuse
  1740. *
  1741. * INPUT
  1742. *
  1743. * OUTPUT
  1744. *
  1745. * RETURNS
  1746. *
  1747. * AUTHOR
  1748. *
  1749. *   POV-Ray Team
  1750. *
  1751. * DESCRIPTION
  1752. *
  1753. *   -
  1754. *
  1755. * CHANGES
  1756. *
  1757. *   -
  1758. *
  1759. ******************************************************************************/
  1760.  
  1761. static void Diffuse (Finish, IPoint, Eye, Layer_Normal, Layer_Pigment_Colour, Colour, Attenuation, Object)
  1762. FINISH *Finish;
  1763. VECTOR IPoint, Layer_Normal;
  1764. COLOUR Layer_Pigment_Colour;
  1765. COLOUR Colour;
  1766. RAY    *Eye;
  1767. DBL    Attenuation;
  1768. OBJECT *Object;
  1769. {
  1770.   int i;
  1771.   DBL Light_Source_Depth, Cos_Shadow_Angle;
  1772.   RAY Light_Source_Ray;
  1773.   LIGHT_SOURCE *Light_Source;
  1774.   VECTOR REye;
  1775.   COLOUR Light_Colour;
  1776.  
  1777.   if ((Finish->Diffuse == 0.0) && (Finish->Specular == 0.0) && (Finish->Phong == 0.0))
  1778.   {
  1779.     return;
  1780.   }
  1781.  
  1782.   if (Finish->Specular != 0.0)
  1783.   {
  1784.     REye[X] = -Eye->Direction[X];
  1785.     REye[Y] = -Eye->Direction[Y];
  1786.     REye[Z] = -Eye->Direction[Z];
  1787.   }
  1788.  
  1789.   for (i = 0, Light_Source = Frame.Light_Sources;
  1790.        Light_Source != NULL;
  1791.        Light_Source = Light_Source->Next_Light_Source, i++)
  1792.   {
  1793.     /* Get a colour and a ray. */
  1794.  
  1795.     do_light(Light_Source, &Light_Source_Depth, &Light_Source_Ray, Eye, IPoint, Light_Colour);
  1796.  
  1797.     /* Don't calculate spotlights when outside of the light's cone. */
  1798.  
  1799.     if ((fabs(Light_Colour[RED])   < BLACK_LEVEL) &&
  1800.         (fabs(Light_Colour[GREEN]) < BLACK_LEVEL) &&
  1801.         (fabs(Light_Colour[BLUE])  < BLACK_LEVEL))
  1802.     {
  1803.       continue;
  1804.     }
  1805.  
  1806.     /* See if light on far side of surface from camera. */
  1807.  
  1808.     if (!(Object->Type & DOUBLE_ILLUMINATE))
  1809.     {
  1810.       VDot(Cos_Shadow_Angle, Layer_Normal, Light_Source_Ray.Direction);
  1811.  
  1812.       if (Cos_Shadow_Angle < EPSILON)
  1813.       {
  1814.         continue;
  1815.       }
  1816.     }
  1817.  
  1818.     /*
  1819.      * If light source was not blocked by any intervening object, then
  1820.      * calculate it's contribution to the object's overall illumination.
  1821.      */
  1822.  
  1823.     if ((opts.Quality_Flags & Q_SHADOW) && (Light_Source->Light_Type != FILL_LIGHT_SOURCE))
  1824.     {
  1825.       /* If this surface point has already been tested use previous result. */
  1826.  
  1827.       if (Light_List[i].Tested)
  1828.       {
  1829.         Assign_Colour(Light_Colour, Light_List[i].Colour);
  1830.       }
  1831.       else
  1832.       {
  1833.         block_light_source(Light_Source, Light_Source_Depth, &Light_Source_Ray, Eye, IPoint, Light_Colour);
  1834.  
  1835.         /* Store light colour. */
  1836.  
  1837.         Light_List[i].Tested = TRUE;
  1838.  
  1839.         Assign_Colour(Light_List[i].Colour, Light_Colour);
  1840.       }
  1841.     }
  1842.  
  1843.     if ((fabs(Light_Colour[RED])   > BLACK_LEVEL) ||
  1844.         (fabs(Light_Colour[GREEN]) > BLACK_LEVEL) ||
  1845.         (fabs(Light_Colour[BLUE])  > BLACK_LEVEL))
  1846.     {
  1847.       if (Finish->Diffuse > 0.0)
  1848.       {
  1849.         do_diffuse(Finish,&Light_Source_Ray,Layer_Normal,Colour,Light_Colour,Layer_Pigment_Colour, Attenuation);
  1850.       }
  1851.  
  1852.       if (Light_Source->Light_Type!=FILL_LIGHT_SOURCE)
  1853.       {
  1854.         if (Finish->Phong > 0.0)
  1855.         {
  1856.           do_phong(Finish,&Light_Source_Ray,Eye->Direction,Layer_Normal,Colour,Light_Colour, Layer_Pigment_Colour);
  1857.         }
  1858.  
  1859.         if (Finish->Specular > 0.0)
  1860.         {
  1861.           do_specular(Finish,&Light_Source_Ray,REye,Layer_Normal,Colour,Light_Colour, Layer_Pigment_Colour);
  1862.         }
  1863.       }
  1864.  
  1865.       if (Finish->Irid > 0.0)
  1866.       {
  1867.         do_irid(Finish,&Light_Source_Ray,Layer_Normal,IPoint,Colour);
  1868.       }
  1869.  
  1870.     }
  1871.   }
  1872. }
  1873.  
  1874.  
  1875.  
  1876. /*****************************************************************************
  1877. *
  1878. * FUNCTION
  1879. *
  1880. *   Reflect
  1881. *
  1882. * INPUT
  1883. *   
  1884. * OUTPUT
  1885. *   
  1886. * RETURNS
  1887. *   
  1888. * AUTHOR
  1889. *
  1890. *   POV-Ray Team
  1891. *   
  1892. * DESCRIPTION
  1893. *
  1894. *   -
  1895. *
  1896. * CHANGES
  1897. *
  1898. *   -
  1899. *
  1900. ******************************************************************************/
  1901.  
  1902. static void Reflect (Reflection, IPoint, Ray, Layer_Normal, Colour, Weight)
  1903. RGB Reflection;
  1904. VECTOR IPoint;
  1905. RAY *Ray;
  1906. VECTOR Layer_Normal;
  1907. COLOUR Colour;
  1908. DBL Weight;
  1909. {
  1910.   RAY New_Ray;
  1911.   COLOUR Temp_Colour;
  1912.   register DBL Normal_Component;
  1913.  
  1914.   Increase_Counter(stats[Reflected_Rays_Traced]);
  1915.  
  1916.   VDot(Normal_Component, Ray->Direction, Layer_Normal);
  1917.  
  1918.   Normal_Component *= -2.0;
  1919.  
  1920.   VLinComb2(New_Ray.Direction, Normal_Component, Layer_Normal, 1.0, Ray->Direction);
  1921.  
  1922.   Assign_Vector(New_Ray.Initial, IPoint);
  1923.  
  1924.   Copy_Ray_Containers (&New_Ray, Ray);
  1925.  
  1926.   /* Trace reflected ray. */
  1927.  
  1928.   Trace_Level++;
  1929.  
  1930.   Make_Colour (Temp_Colour, 0.0, 0.0, 0.0);
  1931.  
  1932.   Trace (&New_Ray, Temp_Colour, Weight);
  1933.  
  1934.   Trace_Level--;
  1935.  
  1936.   Colour[RED]   += Reflection[RED]   * Temp_Colour[RED];
  1937.   Colour[GREEN] += Reflection[GREEN] * Temp_Colour[GREEN];
  1938.   Colour[BLUE]  += Reflection[BLUE]  * Temp_Colour[BLUE];
  1939. }
  1940.  
  1941.  
  1942.  
  1943. /*****************************************************************************
  1944. *
  1945. * FUNCTION
  1946. *
  1947. *   Refract
  1948. *
  1949. * INPUT
  1950. *   
  1951. * OUTPUT
  1952. *   
  1953. * RETURNS
  1954. *
  1955. * AUTHOR
  1956. *
  1957. *   POV-Ray Team
  1958. *   
  1959. * DESCRIPTION
  1960. *
  1961. *   -
  1962. *
  1963. * CHANGES
  1964. *
  1965. *   Aug 1995 : Modified to correctly handle the contained texture
  1966. *              list in the transmitonly case. [DB]
  1967. *
  1968. ******************************************************************************/
  1969.  
  1970. static void Refract (Object, Texture, IPoint, Ray, Top_Normal, Colour, Weight)
  1971. OBJECT *Object;
  1972. TEXTURE *Texture;
  1973. VECTOR IPoint;
  1974. RAY *Ray;
  1975. VECTOR Top_Normal;
  1976. COLOUR Colour;
  1977. DBL Weight;
  1978. {
  1979.   int texture_nr;
  1980.   register DBL Normal_Component, Temp_IOR;
  1981.   DBL temp, ior;
  1982.   VECTOR Local_Normal;
  1983.   RGB Reflection;
  1984.   COLOUR Temp_Colour;
  1985.   RAY New_Ray;
  1986.  
  1987.   /* Do we have to bend the ray? */
  1988.  
  1989.   if (Top_Normal == NULL)
  1990.   {
  1991.     /* Only transmit the ray. */
  1992.  
  1993.     Assign_Vector(New_Ray.Initial, IPoint);
  1994.     Assign_Vector(New_Ray.Direction, Ray->Direction);
  1995.  
  1996.     Copy_Ray_Containers (&New_Ray, Ray);
  1997.  
  1998.     /* Handle contained textures. */
  1999.  
  2000.     if (Ray->Containing_Index == -1)
  2001.     {
  2002.       /* The ray is entering from the atmosphere */
  2003.  
  2004.       Ray_Enter (&New_Ray, Texture, Object);
  2005.     }
  2006.     else
  2007.     {
  2008.       /* The ray is currently inside an object */
  2009.  
  2010.       if ((texture_nr = Texture_In_Ray_Container(&New_Ray, Texture)) >= 0)
  2011.       {
  2012.         /* The ray is leaving the current object */
  2013.  
  2014.         Ray_Exit (&New_Ray, texture_nr);
  2015.       }
  2016.       else
  2017.       {
  2018.         /* The ray is entering a new object */
  2019.  
  2020.         Ray_Enter (&New_Ray, Texture, Object);
  2021.       }
  2022.     }
  2023.  
  2024.     /* Trace transmitted ray. */
  2025.  
  2026.     Trace_Level++;
  2027.  
  2028.     Increase_Counter(stats[Transmitted_Rays_Traced]);
  2029.  
  2030.     Make_Colour (Temp_Colour, 0.0, 0.0, 0.0);
  2031.  
  2032.     Trace (&New_Ray, Temp_Colour, Weight);
  2033.  
  2034.     Trace_Level--;
  2035.  
  2036.     VAddEq(Colour, Temp_Colour);
  2037.   }
  2038.   else
  2039.   {
  2040.     /* Refract the ray. */
  2041.  
  2042.     Increase_Counter(stats[Refracted_Rays_Traced]);
  2043.  
  2044.     VDot (Normal_Component, Ray->Direction, Top_Normal);
  2045.  
  2046.     if (Normal_Component <= 0.0)
  2047.     {
  2048.       Assign_Vector(Local_Normal, Top_Normal);
  2049.  
  2050.       Normal_Component *= -1.0;
  2051.     }
  2052.     else
  2053.     {
  2054.       VScale (Local_Normal, Top_Normal, -1.0);
  2055.     }
  2056.  
  2057.     Copy_Ray_Containers (&New_Ray, Ray);
  2058.  
  2059.     /* Handle contained textures. */
  2060.  
  2061.     if (Ray->Containing_Index == -1)
  2062.     {
  2063.       /* The ray is entering from the atmosphere */
  2064.  
  2065.       Ray_Enter (&New_Ray, Texture, Object);
  2066.  
  2067.       ior = Frame.Atmosphere_IOR / Texture->Finish->Index_Of_Refraction;
  2068.     }
  2069.     else
  2070.     {
  2071.       /* The ray is currently inside an object */
  2072.  
  2073.       if ((texture_nr = Texture_In_Ray_Container(&New_Ray, Texture)) >= 0)
  2074.       {
  2075.         /* The ray is leaving the current object */
  2076.  
  2077.         Ray_Exit (&New_Ray, texture_nr);
  2078.  
  2079.         if (New_Ray.Containing_Index == -1)
  2080.         {
  2081.           /* The ray is leaving into the atmosphere */
  2082.  
  2083.           Temp_IOR = Frame.Atmosphere_IOR;
  2084.         }
  2085.         else
  2086.         {
  2087.           /* The ray is leaving into another object */
  2088.  
  2089.           Temp_IOR = New_Ray.Containing_IORs[New_Ray.Containing_Index];
  2090.         }
  2091.  
  2092.         ior = Texture->Finish->Index_Of_Refraction / Temp_IOR;
  2093.       }
  2094.       else
  2095.       {
  2096.         /* The ray is entering a new object */
  2097.  
  2098.         Temp_IOR = New_Ray.Containing_IORs[New_Ray.Containing_Index];
  2099.  
  2100.         Ray_Enter (&New_Ray, Texture, Object);
  2101.  
  2102.         ior = Temp_IOR / Texture->Finish->Index_Of_Refraction;
  2103.       }
  2104.     }
  2105.  
  2106.     /* Compute refrated ray direction using Heckbert's method. */
  2107.  
  2108.     temp = 1.0 + Sqr(ior) * (Sqr(Normal_Component) - 1.0);
  2109.  
  2110.     if (temp < 0.0)
  2111.     {
  2112.       /* Total internal reflection occures. */
  2113.  
  2114.       Reflection[RED]  = 1.0 - Texture->Finish->Reflection[RED];
  2115.       Reflection[GREEN]= 1.0 - Texture->Finish->Reflection[GREEN];
  2116.       Reflection[BLUE] = 1.0 - Texture->Finish->Reflection[BLUE];
  2117.  
  2118.       Reflect (Reflection, IPoint, Ray, Top_Normal, Colour, Weight);
  2119.  
  2120.       return;
  2121.     }
  2122.  
  2123.     temp = ior * Normal_Component - sqrt(temp);
  2124.  
  2125.     VLinComb2(New_Ray.Direction, ior, Ray->Direction, temp, Local_Normal);
  2126.  
  2127.     Assign_Vector(New_Ray.Initial,IPoint);
  2128.  
  2129.     /* Trace refracted ray. */
  2130.  
  2131.     Trace_Level++;
  2132.  
  2133.     Make_Colour (Temp_Colour, 0.0, 0.0, 0.0);
  2134.  
  2135.     Trace (&New_Ray, Temp_Colour, Weight);
  2136.  
  2137.     Trace_Level--;
  2138.  
  2139.     VAddScaledEq(Colour, Texture->Finish->Refraction, Temp_Colour);
  2140.   }
  2141. }
  2142.  
  2143.  
  2144.  
  2145. /*****************************************************************************
  2146. *
  2147. * FUNCTION
  2148. *
  2149. *   create_texture_list
  2150. *
  2151. * INPUT
  2152. *
  2153. * OUTPUT
  2154. *
  2155. * RETURNS
  2156. *
  2157. * AUTHOR
  2158. *
  2159. *   Chris Young based on Dieter Bayer code
  2160. *   
  2161. * DESCRIPTION
  2162. *
  2163. *   Get the list of textures used by current object and the list of
  2164. *   appropriate weights for each texture. Only multi-colored objects
  2165. *   will have more than one texture.
  2166. *
  2167. * CHANGES
  2168. *
  2169. *   Feb 1995 : Added code for triangle mesh texturing. [DB]
  2170. *
  2171. *   Jul 1995 : Modified code to use pre-allocated lists. [DB]
  2172. *
  2173. ******************************************************************************/
  2174.  
  2175. static int create_texture_list(Ray_Intersection)
  2176. INTERSECTION *Ray_Intersection;
  2177. {
  2178.   int Texture_Count;
  2179.   BLOB *Blob;
  2180.   MESH_TRIANGLE *Triangle;
  2181.  
  2182.   /* Test, if object is multi-textured. */
  2183.  
  2184.   if (Test_Flag(Ray_Intersection->Object, MULTITEXTURE_FLAG))
  2185.   {
  2186.     /* Handle blobs. */
  2187.  
  2188.     if (Ray_Intersection->Object->Methods == &Blob_Methods)
  2189.     {
  2190.       Blob = (BLOB *)Ray_Intersection->Object;
  2191.  
  2192.       /* Get list of weighted textures. */
  2193.  
  2194.       Determine_Blob_Textures(Blob, Ray_Intersection->IPoint, &Texture_Count, Texture_List, Weight_List);
  2195.     }
  2196.  
  2197.     /* Handle meshes. */
  2198.  
  2199.     if (Ray_Intersection->Object->Methods == &Mesh_Methods)
  2200.     {
  2201.       /* Set texture to triangle's or object's texture. */
  2202.  
  2203.       Triangle = (MESH_TRIANGLE *)Ray_Intersection->Pointer;
  2204.  
  2205.       if (Triangle->Texture >= 0)
  2206.       {
  2207.         Texture_List[0] = ((MESH *)Ray_Intersection->Object)->Data->Textures[Triangle->Texture];
  2208.       }
  2209.       else
  2210.       {
  2211.         Texture_List[0] = Ray_Intersection->Object->Texture;
  2212.       }
  2213.  
  2214.       Weight_List[0] = 1.0;
  2215.  
  2216.       Texture_Count = 1;
  2217.     }
  2218.   }
  2219.   else
  2220.   {
  2221.     /* Set texture to object's texture. */
  2222.  
  2223.     Texture_List[0] = Ray_Intersection->Object->Texture;
  2224.     Weight_List[0]  = 1.0;
  2225.  
  2226.     Texture_Count = 1;
  2227.   }
  2228.  
  2229.   return(Texture_Count);
  2230. }
  2231.  
  2232.  
  2233.  
  2234. /*****************************************************************************
  2235. *
  2236. * FUNCTION
  2237. *
  2238. *   do_texture_map
  2239. *
  2240. * INPUT
  2241. *
  2242. *   Texture          - possibly texture_mapped texture to be evaluated
  2243. *   IPoint           - point to be evaluated
  2244. *   Raw_Normal       - non-purturbed surface normal
  2245. *   Ray              - view ray needed for reflection and highlighs
  2246. *                      light source ray needed for caustics
  2247. *   Weight           - ADC control value
  2248. *   Ray_Intersection - only Ray_Int..->Object->Type actually
  2249. *                      needed.  Will clean-up later.
  2250. *   Shadow_Flag      - tells if computation should use
  2251. *                      compute_lighted_texture or compute_shadow_texture
  2252. *
  2253. * OUTPUT
  2254. *
  2255. *   Result_Colour    - If Shadow_Flag true then the illuminated
  2256. *                      color (RGB only) of IPoint is returned.
  2257. *                      If false, the amount by which a shadow ray is
  2258. *                      filtered and attenuated is returned.
  2259. *                      Includes RGB and T.
  2260. *
  2261. * RETURNS
  2262. *
  2263. * AUTHOR
  2264. *
  2265. *   POV-Ray Team
  2266. *
  2267. * DESCRIPTION
  2268. *
  2269. *   This routine recursively calls itself until it gets a
  2270. *   non-texture_mapped texture that is potentially layered.
  2271. *   It then calls compute_lighted_texture or compute_shadow_texture
  2272. *   to compute the color which is returned in the argument Result_Colour.
  2273. *
  2274. * CHANGES
  2275. *
  2276. ******************************************************************************/
  2277.  
  2278. static void do_texture_map(Result_Colour, Texture, IPoint, Raw_Normal,
  2279.   Ray, Weight, Ray_Intersection, Shadow_Flag)
  2280. COLOUR Result_Colour;
  2281. TEXTURE *Texture;
  2282. VECTOR IPoint, Raw_Normal;
  2283. RAY *Ray;
  2284. DBL Weight;
  2285. INTERSECTION *Ray_Intersection;
  2286. int Shadow_Flag;
  2287. {
  2288.   BLEND_MAP *Blend_Map = Texture->Blend_Map;
  2289.   BLEND_MAP_ENTRY *Prev, *Cur;
  2290.   DBL value1, value2;
  2291.   COLOUR C2;
  2292.   VECTOR TPoint;
  2293.  
  2294.   if (Texture->Type <= LAST_SPECIAL_PATTERN)
  2295.   {
  2296.     switch (Texture->Type)
  2297.     {
  2298.       case NO_PATTERN:
  2299.  
  2300.         Make_ColourA(Result_Colour, 1.0, 1.0, 1.0, 1.0, 1.0);
  2301.  
  2302.         break;
  2303.  
  2304.       case AVERAGE_PATTERN:
  2305.  
  2306.         Warp_EPoint(TPoint, IPoint, (TPATTERN *)Texture);
  2307.  
  2308.         average_textures(Result_Colour, Texture, TPoint, Raw_Normal, Ray, Weight, Ray_Intersection, Shadow_Flag);
  2309.  
  2310.         break;
  2311.  
  2312.       case BITMAP_PATTERN:
  2313.  
  2314.         Warp_EPoint (TPoint, IPoint, (TPATTERN *)Texture);
  2315.  
  2316.         Texture = material_map(TPoint, Texture);
  2317.  
  2318.         do_texture_map(Result_Colour, Texture, TPoint, Raw_Normal, Ray, Weight, Ray_Intersection, Shadow_Flag);
  2319.  
  2320.         break;
  2321.  
  2322.       case PLAIN_PATTERN:
  2323.  
  2324.         if (Shadow_Flag)
  2325.         {
  2326.           compute_shadow_texture(Result_Colour, Texture, IPoint, Raw_Normal, Ray, Ray_Intersection);
  2327.         }
  2328.         else
  2329.         {
  2330.           compute_lighted_texture(Result_Colour, Texture, IPoint, Raw_Normal, Ray, Weight, Ray_Intersection);
  2331.         }
  2332.  
  2333.         break;
  2334.  
  2335.       default:
  2336.  
  2337.         Error("Bad texture type in do_texture_map()\n");
  2338.     }
  2339.   }
  2340.   else
  2341.   {
  2342.     value1 = Evaluate_TPat ((TPATTERN *)Texture,IPoint);
  2343.  
  2344.     Search_Blend_Map (value1, Blend_Map, &Prev, &Cur);
  2345.  
  2346.     Warp_EPoint (TPoint, IPoint, (TPATTERN *)Texture);
  2347.  
  2348.     do_texture_map(Result_Colour, Cur->Vals.Texture, TPoint, Raw_Normal, Ray, Weight, Ray_Intersection, Shadow_Flag);
  2349.  
  2350.     if (Prev != Cur)
  2351.     {
  2352.       do_texture_map(C2, Prev->Vals.Texture, TPoint, Raw_Normal, Ray, Weight, Ray_Intersection, Shadow_Flag);
  2353.  
  2354.       value1 = (value1 - Prev->value) / (Cur->value - Prev->value);
  2355.       value2 = 1.0 - value1;
  2356.  
  2357.       CLinComb2(Result_Colour,value1,Result_Colour,value2,C2);
  2358.     }
  2359.   }
  2360. }
  2361.  
  2362.  
  2363.  
  2364.  
  2365. /*****************************************************************************
  2366. *
  2367. * FUNCTION
  2368. *
  2369. *   compute_lighted_texture
  2370. *
  2371. * INPUT
  2372. *
  2373. *   Texture          - a linked list of texture layers
  2374. *   IPoint           - point to be evaluated
  2375. *   Raw_Normal       - non-purturbed surface normal
  2376. *   Ray              - needed for reflection and highlighs
  2377. *   Weight           - ADC control value
  2378. *   Ray_Intersection - current intersection (need object type and depth)
  2379. *
  2380. * OUTPUT
  2381. *
  2382. *   Result_Colour    - illuminated color of IPoint
  2383. *
  2384. * RETURNS
  2385. *
  2386. * AUTHOR
  2387. *
  2388. *   POV-Ray Team
  2389. *
  2390. * DESCRIPTION
  2391. *
  2392. *   This routine loops through all layers of a texture and computes
  2393. *   the appearent color of the point with illumination, shadows,
  2394. *   reflection, refraction... everything.  This piece of code was broken out
  2395. *   of Determine_Appearent_Colour because texture_map needs to call it twice.
  2396. *
  2397. * CHANGES
  2398. *
  2399. *   Jul 1995 : Added code to support alpha channel. [DB]
  2400. *
  2401. *   Jul 1995 : Moved code for save list allocation. [DB]
  2402. *
  2403. *   Aug 1995 : Added code for distance based attenuation in translucent
  2404. *              objects and halos. [DB]
  2405. *
  2406. ******************************************************************************/
  2407.  
  2408. static void compute_lighted_texture(Result_Colour, Texture, IPoint, Raw_Normal, Ray, Weight, Ray_Intersection)
  2409. COLOUR Result_Colour;
  2410. TEXTURE *Texture;
  2411. VECTOR IPoint, Raw_Normal;
  2412. RAY *Ray;
  2413. DBL Weight;
  2414. INTERSECTION *Ray_Intersection;
  2415. {
  2416.   int i, radiosity_done, radiosity_needed;
  2417.   int layer_number;
  2418.   int calc_halo;
  2419.   int one_colour_found, colour_found;
  2420.   DBL w1, w2;
  2421.   DBL Normal_Direction, New_Weight, Temp_Weight;
  2422.   DBL Attenuation, Transparency, Max_Radiosity_Contribution;
  2423.   VECTOR Layer_Normal, Top_Normal;
  2424.   COLOUR Layer_Pigment_Colour, Refracted_Colour, Filter_Colour;
  2425.   COLOUR Temp_Colour, Gathered_Ambient_Colour, Temp;
  2426.   FINISH *Finish;
  2427.   HALO *Halo;
  2428.   TEXTURE *Layer;
  2429.  
  2430.   /*
  2431.    * Result_Colour builds up the apparent visible color of the point.
  2432.    * Only RGB components are significant.  You can't "see" transparency --
  2433.    * you see the color of whatever is behind the transparent surface.
  2434.    * This color includes the visible appearence of what is behind the
  2435.    * transparency so only RGB is needed.
  2436.    */
  2437.  
  2438.   Make_ColourA(Result_Colour, 0.0, 0.0, 0.0, 0.0, 0.0);
  2439.  
  2440.   /*
  2441.    * Filter_Colour serves two purposes.  It accumulates the filter properties
  2442.    * of a multi-layer texture so that if a ray makes it all the way through
  2443.    * all layers, the color of object behind is filtered by this object.
  2444.    * It also is used to attenuate how much of an underlayer you
  2445.    * can see in a layered texture.  Note that when computing the reflective
  2446.    * properties of a layered texture, the upper layers don't filter the
  2447.    * light from the lower layers -- the layer colors add together (even
  2448.    * before we added additive transparency via the "transmit" 5th
  2449.    * color channel).  However when computing the transmitted rays, all layers
  2450.    * filter the light from any objects behind this object. [CY 1/95]
  2451.    */
  2452.  
  2453.   Make_ColourA(Filter_Colour, 1.0, 1.0, 1.0, 1.0, 1.0);
  2454.  
  2455.   Transparency = 1.0;
  2456.  
  2457.   /* add in radiosity (stochastic interreflection-based ambient light) if desired */
  2458.  
  2459.   radiosity_done = FALSE;
  2460.  
  2461.   /* Note that there is no gathering of filter or transparency */
  2462.  
  2463.   Make_ColourA(Gathered_Ambient_Colour, 1., 1., 1., 0., 0.);
  2464.  
  2465.   if ((opts.Options & RADIOSITY) &&
  2466.       (Trace_Level == Radiosity_Trace_Level) &&
  2467.       (Radiosity_Trace_Level <= opts.Radiosity_Recursion_Limit))
  2468.   {
  2469.     /*
  2470.      * For "real" (physically-based) diffuse interreflections, the
  2471.      * ambient light level is independent of any surface properties, so
  2472.      * the light gathering is done only once.  This block just sets up
  2473.      * for the code inside the loop, which is first-time-through.
  2474.      */
  2475.  
  2476.     /* If the surface normal points away, flip its direction. */
  2477.  
  2478.     VDot(Normal_Direction, Raw_Normal, Ray->Direction);
  2479.  
  2480.     if (Normal_Direction > 0.0)
  2481.     {
  2482.       VScaleEq(Raw_Normal, -1.0);
  2483.     }
  2484.  
  2485.     radiosity_needed = 1;
  2486.   }
  2487.   else
  2488.   {
  2489.     radiosity_needed = 0;
  2490.   }
  2491.  
  2492.   /*
  2493.    * Loop through the layers and compute the ambient, diffuse, reflection
  2494.    * and highlights from these textures.
  2495.    */
  2496.  
  2497.   one_colour_found = FALSE;
  2498.  
  2499.   for (layer_number = 1, Layer = Texture;
  2500.       (Layer != NULL) && (Transparency > BLACK_LEVEL);
  2501.       layer_number++, Layer = (TEXTURE *)Layer->Next)
  2502.   {
  2503.     Assign_Vector(Layer_Normal, Raw_Normal);
  2504.  
  2505.     if ((opts.Quality_Flags & Q_NORMAL) && (Layer->Tnormal != NULL))
  2506.     {
  2507.       Perturb_Normal(Layer_Normal, Layer->Tnormal, IPoint);
  2508.     }
  2509.  
  2510.     /* If the surface normal points away, flip its direction. */
  2511.  
  2512.     VDot(Normal_Direction, Layer_Normal, Ray->Direction);
  2513.  
  2514.     if (Normal_Direction > 0.0)
  2515.     {
  2516.       VScaleEq(Layer_Normal, -1.0);
  2517.     }
  2518.  
  2519.     /* Store top layer normal.*/
  2520.  
  2521.     if (layer_number == 1)
  2522.     {
  2523.       Assign_Vector(Top_Normal,Layer_Normal);
  2524.     }
  2525.  
  2526.     /* Get surface colour. */
  2527.  
  2528.     New_Weight = Weight * Transparency;
  2529.  
  2530.     colour_found = Compute_Pigment (Layer_Pigment_Colour, Layer->Pigment, IPoint);
  2531.  
  2532.     /*
  2533.      * If a valid color was returned set one_colour_found to TRUE.
  2534.      * An invalid color is returned if a surface point is outside
  2535.      * an image map used just once.
  2536.      */
  2537.  
  2538.     if (colour_found)
  2539.     {
  2540.       one_colour_found = TRUE;
  2541.     }
  2542.  
  2543.     /*
  2544.      * This section of code used to be the routine Compute_Reflected_Colour.
  2545.      * I copied it in here to rearrange some of it more easily and to
  2546.      * see if we could eliminate passing a zillion parameters for no
  2547.      * good reason. [CY 1/95]
  2548.      */
  2549.  
  2550.     if (opts.Quality_Flags & Q_FULL_AMBIENT)
  2551.     {
  2552.       /* Only use top layer and kill transparency if low quality */
  2553.  
  2554.       Assign_Colour(Result_Colour, Layer_Pigment_Colour);
  2555.  
  2556.       Result_Colour[FILTER] =
  2557.       Result_Colour[TRANSM] = 0.0;
  2558.     }
  2559.     else
  2560.     {
  2561.       Make_Colour (Temp_Colour, 0.0, 0.0, 0.0);
  2562.  
  2563.       Attenuation = Transparency * (1.0 - min(1.0, Layer_Pigment_Colour[FILTER] + Layer_Pigment_Colour[TRANSM]));
  2564.  
  2565.       /* if radiosity calculation needed, but not yet done, do it now */
  2566.  
  2567.       if (radiosity_needed && !radiosity_done)
  2568.       {
  2569.         /* This check eliminates radiosity calculations on "luminous" objects with ambient=1 */
  2570.  
  2571.         if ((Layer->Finish->Ambient[RED]   != 1.0) ||
  2572.             (Layer->Finish->Ambient[GREEN] != 1.0) ||
  2573.             (Layer->Finish->Ambient[BLUE]  != 1.0))
  2574.         {
  2575.           /* calculate max possible contribution of radiosity, to see if calculating it is worthwhile */
  2576.  
  2577.           Temp[RED]   = Attenuation * Layer_Pigment_Colour[RED] *
  2578.                         Layer->Finish->Ambient[RED] *
  2579.                         Frame.Ambient_Light[RED];
  2580.  
  2581.           Temp[GREEN] = Attenuation * Layer_Pigment_Colour[GREEN] *
  2582.                         Layer->Finish->Ambient[GREEN] *
  2583.                         Frame.Ambient_Light[GREEN];
  2584.  
  2585.           Temp[BLUE]  = Attenuation * Layer_Pigment_Colour[BLUE] *
  2586.                         Layer->Finish->Ambient[BLUE] *
  2587.                         Frame.Ambient_Light[BLUE];
  2588.  
  2589.           Max_Radiosity_Contribution = Temp[RED] *.287 + Temp[GREEN] *.589 + Temp[BLUE] * .114;
  2590.  
  2591.           if (Max_Radiosity_Contribution > BLACK_LEVEL * 3.0)
  2592.           {
  2593.             (void)Compute_Ambient(Ray_Intersection->IPoint, Raw_Normal,
  2594.               Gathered_Ambient_Colour, Weight * Max_Radiosity_Contribution);
  2595.  
  2596.             radiosity_done = TRUE;
  2597.           }
  2598.         }
  2599.       }
  2600.  
  2601.       /* Add ambient contribution. */
  2602.  
  2603.       Temp_Colour[RED]   += Attenuation *
  2604.                             Layer_Pigment_Colour[RED] *
  2605.                             Layer->Finish->Ambient[RED] *
  2606.                             Frame.Ambient_Light[RED] *
  2607.                             Gathered_Ambient_Colour[RED];
  2608.  
  2609.       Temp_Colour[GREEN] += Attenuation *
  2610.                             Layer_Pigment_Colour[GREEN] *
  2611.                             Layer->Finish->Ambient[GREEN] *
  2612.                             Frame.Ambient_Light[GREEN] *
  2613.                             Gathered_Ambient_Colour[GREEN];
  2614.  
  2615.       Temp_Colour[BLUE]  += Attenuation *
  2616.                             Layer_Pigment_Colour[BLUE] *
  2617.                             Layer->Finish->Ambient[BLUE] *
  2618.                             Frame.Ambient_Light[BLUE] *
  2619.                             Gathered_Ambient_Colour[BLUE];
  2620.  
  2621.  
  2622.       /* Add diffuse, phong, specular, and iridescence contribution. */
  2623.  
  2624.       Diffuse (Layer->Finish, Ray_Intersection->IPoint, Ray,
  2625.         Layer_Normal, Layer_Pigment_Colour, Temp_Colour, Attenuation,
  2626.         Ray_Intersection->Object);
  2627.  
  2628.       VAddEq(Result_Colour, Temp_Colour);
  2629.  
  2630.       /* Do reflection. */
  2631.  
  2632.       if (opts.Quality_Flags & Q_REFLECT)
  2633.       {
  2634.         if ((Layer->Finish->Reflection[RED]   != 0.0) ||
  2635.             (Layer->Finish->Reflection[GREEN] != 0.0) ||
  2636.             (Layer->Finish->Reflection[BLUE]  != 0.0))
  2637.         {
  2638.           Temp_Weight = New_Weight * max3(Layer->Finish->Reflection[RED], Layer->Finish->Reflection[GREEN], Layer->Finish->Reflection[BLUE]);
  2639.  
  2640.           Reflect(Layer->Finish->Reflection, Ray_Intersection->IPoint, Ray,
  2641.             Layer_Normal, Result_Colour, Temp_Weight);
  2642.         }
  2643.       }
  2644.     }
  2645.  
  2646.     /*
  2647.      * End of former Compute_Reflected_Colour code.
  2648.      */
  2649.  
  2650.     if (colour_found)
  2651.     {
  2652.       Filter_Colour[RED]    *= Layer_Pigment_Colour[RED];
  2653.       Filter_Colour[GREEN]  *= Layer_Pigment_Colour[GREEN];
  2654.       Filter_Colour[BLUE]   *= Layer_Pigment_Colour[BLUE];
  2655.       Filter_Colour[FILTER] *= Layer_Pigment_Colour[FILTER];
  2656.       Filter_Colour[TRANSM] *= Layer_Pigment_Colour[TRANSM];
  2657.     }
  2658.  
  2659.     Transparency = min(1.0, fabs(Filter_Colour[FILTER]) + fabs(Filter_Colour[TRANSM]));
  2660.   }
  2661.  
  2662.   /*
  2663.    * Now see if any transparency remains.  If it does, then fire a transmitted
  2664.    * ray and add it's contribution to the total Result_Colour after
  2665.    * filtering it by Filter_Colour.
  2666.    */
  2667.  
  2668.   Finish = Texture->Finish;
  2669.  
  2670.   if ((Transparency > BLACK_LEVEL) && (opts.Quality_Flags & Q_REFRACT))
  2671.   {
  2672.     Make_Colour(Refracted_Colour, 0.0, 0.0, 0.0);
  2673.  
  2674.     w1 = fabs(Filter_Colour[FILTER]) * max3(Filter_Colour[RED], Filter_Colour[GREEN], Filter_Colour[BLUE]);
  2675.     w2 = fabs(Filter_Colour[TRANSM]);
  2676.  
  2677.     New_Weight = Weight * max(w1, w2);
  2678.  
  2679.     /*
  2680.      * WARNING: The Refract() routine must be passed the un-transformed
  2681.      * IPoint from Ray_Intersection->IPoint so that the Ray->Initial for
  2682.      * transmitted rays is properly set.  It should not be a TPoint from
  2683.      * some transformed or turbulated texture_map pattern.
  2684.      */
  2685.  
  2686.     if (Finish->Refraction > 0.0)
  2687.     {
  2688.       Refract (Ray_Intersection->Object, Texture, Ray_Intersection->IPoint, Ray, Top_Normal, Refracted_Colour, New_Weight);
  2689.     }
  2690.     else
  2691.     {
  2692.       Refract (Ray_Intersection->Object, Texture, Ray_Intersection->IPoint, Ray, NULL, Refracted_Colour, New_Weight);
  2693.     }
  2694.  
  2695.     /* Get distance based attenuation. */
  2696.  
  2697.     Attenuation = 1.0;
  2698.  
  2699.     if (Ray->Containing_Index > -1)
  2700.     {
  2701.       /* Attenuate light due to light source distance. */
  2702.  
  2703.       if (Texture_In_Ray_Container(Ray, Texture) >= 0)
  2704.       {
  2705.         if ((Finish->Fade_Power > 0.0) && (fabs(Finish->Fade_Distance) > EPSILON))
  2706.         {
  2707.           Attenuation = 1.0 / (1.0 + pow(Ray_Intersection->Depth / Finish->Fade_Distance, Finish->Fade_Power));
  2708.         }
  2709.       }
  2710.     }
  2711.  
  2712.     if (one_colour_found)
  2713.     {
  2714.       Result_Colour[RED]  += Attenuation * Refracted_Colour[RED]   *
  2715.         (Filter_Colour[RED]   * Filter_Colour[FILTER] + Filter_Colour[TRANSM]);
  2716.  
  2717.       Result_Colour[GREEN]+= Attenuation * Refracted_Colour[GREEN] *
  2718.         (Filter_Colour[GREEN] * Filter_Colour[FILTER] + Filter_Colour[TRANSM]);
  2719.  
  2720.       Result_Colour[BLUE] += Attenuation * Refracted_Colour[BLUE]  *
  2721.         (Filter_Colour[BLUE]  * Filter_Colour[FILTER] + Filter_Colour[TRANSM]);
  2722.     }
  2723.     else
  2724.     {
  2725.       Result_Colour[RED]  += Attenuation * Refracted_Colour[RED];
  2726.       Result_Colour[GREEN]+= Attenuation * Refracted_Colour[GREEN];
  2727.       Result_Colour[BLUE] += Attenuation * Refracted_Colour[BLUE];
  2728.     }
  2729.  
  2730.     /* We need to know the transmittance value for the alpha channel. [DB] */
  2731.  
  2732.     Result_Colour[TRANSM] = Attenuation * Filter_Colour[TRANSM];
  2733.   }
  2734.  
  2735.   /* Calculate halo effects. */
  2736.  
  2737.   if ((opts.Quality_Flags & Q_VOLUME) && (Ray->Containing_Index > -1))
  2738.   {
  2739.     calc_halo = TRUE;
  2740.  
  2741.     /* Test for any solid object. */
  2742.  
  2743.     for (i = 0; i <= Ray->Containing_Index; i++)
  2744.     {
  2745.       if (!Test_Flag(Ray->Containing_Objects[i], HOLLOW_FLAG))
  2746.       {
  2747.         calc_halo = FALSE;
  2748.  
  2749.         break;
  2750.       }
  2751.     }
  2752.  
  2753.     /* Calculate effects of all halos we're currently in. */
  2754.  
  2755.     if (calc_halo)
  2756.     {
  2757.       for (i = 0; i <= Ray->Containing_Index; i++)
  2758.       {
  2759.         if ((Halo = Ray->Containing_Textures[i]->Halo) != NULL)
  2760.         {
  2761.           if (Halo->Type != HALO_NO_HALO)
  2762.           {
  2763.             Do_Halo(Halo, Ray, Ray_Intersection, Result_Colour, FALSE);
  2764.           }
  2765.         }
  2766.       }
  2767.     }
  2768.   }
  2769. }
  2770.  
  2771.  
  2772.  
  2773. /*****************************************************************************
  2774. *
  2775. * FUNCTION
  2776. *
  2777. *   compute_shadow_texture
  2778. *
  2779. * INPUT
  2780. *
  2781. *   Texture          - layered texture through which shadow ray passes
  2782. *   IPoint           - point through which shadow ray passes
  2783. *   Raw_Normal       - non-purturbed surface normal
  2784. *   Ray              - light source ray
  2785. *   Ray_Intersection - current intersection (need intersection depth)
  2786. *
  2787. * OUTPUT
  2788. *
  2789. *   Filter_Colour - returned filter for shadow ray
  2790. *
  2791. * RETURNS
  2792. *
  2793. * AUTHOR
  2794. *
  2795. *   POV-Ray Team
  2796. *
  2797. * DESCRIPTION
  2798. *
  2799. * CHANGES
  2800. *
  2801. *   Dec 1994 : Separated from filter_shadow_ray to do texture_map [CEY]
  2802. *
  2803. *   May 1995 : Added caustic code by Steve Anger. [DB]
  2804. *
  2805. *   Aug 1995 : Caustic code moved here from filter_shadow_ray. [CEY]
  2806. *
  2807. ******************************************************************************/
  2808.  
  2809. static void compute_shadow_texture (Filter_Colour, Texture, IPoint, Raw_Normal, Ray, Ray_Intersection)
  2810. COLOUR Filter_Colour;
  2811. TEXTURE *Texture;
  2812. VECTOR IPoint;
  2813. VECTOR Raw_Normal;
  2814. RAY *Ray;
  2815. INTERSECTION *Ray_Intersection;
  2816. {
  2817.   int i, calc_halo, colour_found, one_colour_found;
  2818.   DBL Caustics, dot, k, Refraction;
  2819.   VECTOR Layer_Normal;
  2820.   COLOUR Layer_Pigment_Colour;
  2821.   COLOUR Halo_Colour;
  2822.   FINISH *Finish;
  2823.   HALO *Halo;
  2824.   TEXTURE *Layer;
  2825.  
  2826.   Make_ColourA(Filter_Colour, 1.0, 1.0, 1.0, 1.0, 1.0);
  2827.  
  2828.   one_colour_found = FALSE;
  2829.  
  2830.   for (Layer = Texture; (Layer != NULL) &&
  2831.        (fabs(Filter_Colour[FILTER]) + fabs(Filter_Colour[TRANSM]) > BLACK_LEVEL);
  2832.        Layer = (TEXTURE *)Layer->Next)
  2833.   {
  2834.     colour_found = Compute_Pigment (Layer_Pigment_Colour, Layer->Pigment, IPoint);
  2835.  
  2836.     if (colour_found)
  2837.     {
  2838.       one_colour_found = TRUE;
  2839.     }
  2840.  
  2841.     Refraction = (DBL)((Layer->Finish->Refraction > 0.0) ? Layer->Finish->Refraction : 1.0);
  2842.  
  2843.     /* Get distance based attenuation. */
  2844.  
  2845.     if (Ray->Containing_Index > -1)
  2846.     {
  2847.       /* Get finish of texture we're currently in. */
  2848.  
  2849.       if ((Finish = Ray->Containing_Textures[Ray->Containing_Index]->Finish)!=NULL)
  2850.       {
  2851.          /* Attenuate light due to light source distance. */
  2852.  
  2853.          if (Texture_In_Ray_Container(Ray, Texture) >= 0)
  2854.          {
  2855.            if ((Finish->Fade_Power > 0.0) && (fabs(Finish->Fade_Distance) > EPSILON))
  2856.            {
  2857.              Refraction *= 1.0 / (1.0 + pow(Ray_Intersection->Depth / Finish->Fade_Distance, Finish->Fade_Power));
  2858.            }
  2859.          }
  2860.       }
  2861.     }
  2862.  
  2863.     if (colour_found)
  2864.     {
  2865.       Filter_Colour[RED]    *= Refraction * Layer_Pigment_Colour[RED];
  2866.       Filter_Colour[GREEN]  *= Refraction * Layer_Pigment_Colour[GREEN];
  2867.       Filter_Colour[BLUE]   *= Refraction * Layer_Pigment_Colour[BLUE];
  2868.       Filter_Colour[FILTER] *= Refraction * Layer_Pigment_Colour[FILTER];
  2869.       Filter_Colour[TRANSM] *= Refraction * Layer_Pigment_Colour[TRANSM];
  2870.     }
  2871.     else
  2872.     {
  2873.       Filter_Colour[RED]    *= Refraction;
  2874.       Filter_Colour[GREEN]  *= Refraction;
  2875.       Filter_Colour[BLUE]   *= Refraction;
  2876.       Filter_Colour[FILTER] *= Refraction;
  2877.       Filter_Colour[TRANSM] *= Refraction;
  2878.     }
  2879.  
  2880.     /* Get normal for faked caustics. (Will rewrite later to cache) */
  2881.  
  2882.     if ((Caustics = Layer->Finish->Caustics) != 0.0)
  2883.     {
  2884.       Assign_Vector(Layer_Normal, Raw_Normal);
  2885.  
  2886.       if ((opts.Quality_Flags & Q_NORMAL) && (Layer->Tnormal != NULL))
  2887.       {
  2888.         Perturb_Normal(Layer_Normal, Layer->Tnormal, IPoint);
  2889.       }
  2890.  
  2891.       /* Get new filter/transmit values. */
  2892.  
  2893.       VDot (dot, Layer_Normal, Ray->Direction);
  2894.  
  2895.       k = (1.0 + pow(fabs(dot), Caustics));
  2896.  
  2897.       Filter_Colour[FILTER] *= k;
  2898.       Filter_Colour[TRANSM] *= k;
  2899.     }
  2900.   }
  2901.  
  2902.   /*
  2903.    * If no valid color was found we set the filtering channel
  2904.    * to zero to make sure that no light amplification occures.
  2905.    * That would happen if both the filter and transmit channel
  2906.    * were used.
  2907.    */
  2908.  
  2909.   if (!one_colour_found)
  2910.   {
  2911.     Filter_Colour[FILTER] = 0.0;
  2912.   }
  2913.  
  2914.   /* Calculate halo. */
  2915.  
  2916.   if ((opts.Quality_Flags & Q_VOLUME) && (Ray->Containing_Index > -1))
  2917.   {
  2918.     calc_halo = TRUE;
  2919.  
  2920.     /* Test for any solid object. */
  2921.  
  2922.     for (i = 0; i <= Ray->Containing_Index; i++)
  2923.     {
  2924.       if (!Test_Flag(Ray->Containing_Objects[i], HOLLOW_FLAG))
  2925.       {
  2926.         calc_halo = FALSE;
  2927.  
  2928.         break;
  2929.       }
  2930.     }
  2931.  
  2932.     /* Calculate effects of all halos we're currently in. */
  2933.  
  2934.     if (calc_halo)
  2935.     {
  2936.       for (i = 0; i <= Ray->Containing_Index; i++)
  2937.       {
  2938.         if ((Halo = Ray->Containing_Textures[i]->Halo) != NULL)
  2939.         {
  2940.           if (Halo->Type != HALO_NO_HALO)
  2941.           {
  2942.             Do_Halo(Halo, Ray, Ray_Intersection, Halo_Colour, TRUE);
  2943.           }
  2944.         }
  2945.       }
  2946.     }
  2947.   }
  2948. }
  2949.  
  2950.  
  2951.  
  2952. /*****************************************************************************
  2953. *
  2954. * FUNCTION
  2955. *
  2956. *   filter_shadow_ray
  2957. *
  2958. * INPUT
  2959. *
  2960. * OUTPUT
  2961. *
  2962. * RETURNS
  2963. *
  2964. * AUTHOR
  2965. *
  2966. *   POV-Ray Team
  2967. *
  2968. * DESCRIPTION
  2969. *
  2970. *   -
  2971. *
  2972. * CHANGES
  2973. *
  2974. *   Aug 1994 : Code for early exit due to opaque object added. [DB]
  2975. *
  2976. *   Sep 1994 : Code for multi-textured blobs added. [DB]
  2977. *
  2978. *   May 1995 : Added caustic code by Steve Anger. [DB]
  2979. *
  2980. *   Aug 1995 : Added code to attenuate light source color
  2981. *              due to atmospheric effects. [DB]
  2982. *
  2983. ******************************************************************************/
  2984.  
  2985. static void filter_shadow_ray(Ray_Intersection, Light_Source_Ray, Colour)
  2986. INTERSECTION *Ray_Intersection;
  2987. RAY *Light_Source_Ray;
  2988. COLOUR Colour;
  2989. {
  2990.   int i, Texture_Count;
  2991.   VECTOR IPoint;
  2992.   VECTOR Raw_Normal;
  2993.   COLOUR FC1, Temp_Colour;
  2994.   TEXTURE *Texture = NULL;  /* To remove uninitialized use warning [AED] */
  2995.  
  2996.   Assign_Vector(IPoint, Ray_Intersection->IPoint);
  2997.  
  2998.   if (!(opts.Quality_Flags & Q_SHADOW))
  2999.   {
  3000.     return;
  3001.   }
  3002.  
  3003.   /* If the object is opaque there's no need to go any further. [DB 8/94] */
  3004.  
  3005.   if (Test_Flag(Ray_Intersection->Object, OPAQUE_FLAG))
  3006.   {
  3007.     Make_Colour(Colour, 0.0, 0.0, 0.0);
  3008.  
  3009.     return;
  3010.   }
  3011.  
  3012.   /* Get the normal to the surface */
  3013.  
  3014.   Normal(Raw_Normal, Ray_Intersection->Object, Ray_Intersection);
  3015.  
  3016.   /* Get texture list and weights. */
  3017.  
  3018.   Texture_Count = create_texture_list(Ray_Intersection);
  3019.  
  3020.   Make_ColourA(Temp_Colour, 0.0, 0.0, 0.0, 0.0, 0.0);
  3021.  
  3022.   for (i = 0; i < Texture_Count; i++)
  3023.   {
  3024.     /* If contribution of this texture is neglectable skip ahead. */
  3025.  
  3026.     if (Weight_List[i] < BLACK_LEVEL)
  3027.     {
  3028.       continue;
  3029.     }
  3030.  
  3031.     Texture = Texture_List[i];
  3032.  
  3033.     do_texture_map(FC1, Texture, IPoint, Raw_Normal, Light_Source_Ray, 0.0, Ray_Intersection, TRUE);
  3034.  
  3035.     Temp_Colour[RED]     += Weight_List[i] * FC1[RED];
  3036.     Temp_Colour[GREEN]   += Weight_List[i] * FC1[GREEN];
  3037.     Temp_Colour[BLUE]    += Weight_List[i] * FC1[BLUE];
  3038.     Temp_Colour[FILTER]  += Weight_List[i] * FC1[FILTER];
  3039.     Temp_Colour[TRANSM]  += Weight_List[i] * FC1[TRANSM];
  3040.   }
  3041.  
  3042.   if (fabs(Temp_Colour[FILTER]) + fabs(Temp_Colour[TRANSM]) < BLACK_LEVEL)
  3043.   {
  3044.     Make_Colour(Colour, 0.0, 0.0, 0.0);
  3045.   }
  3046.   else
  3047.   {
  3048.     Colour[RED]   *= Temp_Colour[FILTER] * Temp_Colour[RED]  + Temp_Colour[TRANSM];
  3049.     Colour[GREEN] *= Temp_Colour[FILTER] * Temp_Colour[GREEN]+ Temp_Colour[TRANSM];
  3050.     Colour[BLUE]  *= Temp_Colour[FILTER] * Temp_Colour[BLUE] + Temp_Colour[TRANSM];
  3051.   }
  3052.  
  3053.   /* Get atmospheric attenuation. */
  3054.  
  3055.   do_light_ray_atmosphere(Light_Source_Ray, Ray_Intersection, Texture, Colour, TRUE);
  3056. }
  3057.  
  3058.  
  3059.  
  3060. /*****************************************************************************
  3061. *
  3062. * FUNCTION
  3063. *
  3064. *   do_blocking
  3065. *
  3066. * INPUT
  3067. *
  3068. * OUTPUT
  3069. *
  3070. * RETURNS
  3071. *
  3072. * AUTHOR
  3073. *
  3074. *   POV-Ray Team
  3075. *
  3076. * DESCRIPTION
  3077. *
  3078. *   -
  3079. *
  3080. * CHANGES
  3081. *
  3082. *   -
  3083. *
  3084. ******************************************************************************/
  3085.  
  3086. static int do_blocking(Local_Intersection, Light_Source_Ray, Light_Colour, Local_Stack)
  3087. INTERSECTION *Local_Intersection;
  3088. RAY *Light_Source_Ray;
  3089. COLOUR Light_Colour;
  3090. ISTACK *Local_Stack;
  3091. {
  3092.   Increase_Counter(stats[Shadow_Rays_Succeeded]);
  3093.  
  3094.   filter_shadow_ray(Local_Intersection, Light_Source_Ray, Light_Colour);
  3095.  
  3096.   if ((fabs(Light_Colour[RED])   < BLACK_LEVEL) &&
  3097.       (fabs(Light_Colour[GREEN]) < BLACK_LEVEL) &&
  3098.       (fabs(Light_Colour[BLUE])  < BLACK_LEVEL))
  3099.   {
  3100.     while ((Local_Intersection = pop_entry(Local_Stack)) != NULL)
  3101.     {
  3102.     }
  3103.  
  3104.     return(TRUE);
  3105.   }
  3106.  
  3107.   return(FALSE);
  3108. }
  3109.  
  3110.  
  3111.  
  3112. /*****************************************************************************
  3113. *
  3114. * FUNCTION
  3115. *
  3116. *   block_light_source
  3117. *
  3118. * INPUT
  3119. *
  3120. *   Light            - Light source
  3121. *   Depth            - Distance to light source
  3122. *   Light_Source_Ray - Light ray
  3123. *   Eye_Ray          - Ray from eye to current intersection point
  3124. *   P                - Surface point to shade
  3125. *
  3126. * OUTPUT
  3127. *
  3128. *   Colour           - Light color reaching point P
  3129. *
  3130. * RETURNS
  3131. *
  3132. * AUTHOR
  3133. *
  3134. *   Dieter Bayer
  3135. *
  3136. * DESCRIPTION
  3137. *
  3138. *   Determine how much light from the given light source reaches
  3139. *   the given point. This includes attenuation due to blocking
  3140. *   and translucent objects and atmospheric effects.
  3141. *
  3142. * CHANGES
  3143. *
  3144. *   Jan 1995 : Creation (Extracted from common code).
  3145. *
  3146. *   Aug 1995 : Added code to support atmospheric effects. [DB]
  3147. *
  3148. ******************************************************************************/
  3149.  
  3150. static void block_light_source(Light, Depth, Light_Source_Ray, Eye_Ray, P, Colour)
  3151. LIGHT_SOURCE *Light;
  3152. DBL Depth;
  3153. RAY *Light_Source_Ray, *Eye_Ray;
  3154. VECTOR P;
  3155. COLOUR Colour;
  3156. {
  3157.   DBL New_Depth;
  3158.   INTERSECTION Intersection;
  3159.   RAY New_Ray;
  3160.  
  3161.   /* Store current depth and ray because they will be modified. */
  3162.  
  3163.   New_Depth = Depth;
  3164.  
  3165.   New_Ray = *Light_Source_Ray;
  3166.  
  3167.   /* Get shadows from current light source. */
  3168.  
  3169.   if ((Light->Area_Light) && (opts.Quality_Flags & Q_AREA_LIGHT))
  3170.   {
  3171.     block_area_light(Light, &New_Depth, &New_Ray, Eye_Ray, P, Colour, 0, 0, 0, 0, 0);
  3172.   }
  3173.   else
  3174.   {
  3175.     if (opts.Options & USE_LIGHT_BUFFER)
  3176.     {
  3177.       block_point_light_LBuffer(Light, &New_Depth, &New_Ray, Colour);
  3178.     }
  3179.     else
  3180.     {
  3181.       block_point_light(Light, &New_Depth, &New_Ray, Colour);
  3182.     }
  3183.   }
  3184.  
  3185.   /*
  3186.    * If there's some distance left for the ray to reach the light source
  3187.    * we have to apply atmospheric stuff to this part of the ray.
  3188.    */
  3189.  
  3190.   if ((New_Depth > SHADOW_TOLERANCE) &&
  3191.       (Light->Atmosphere_Interaction) &&
  3192.       (Light->Atmospheric_Attenuation))
  3193.   {
  3194.     Intersection.Depth = New_Depth;
  3195.  
  3196.     do_light_ray_atmosphere(&New_Ray, &Intersection, NULL, Colour, FALSE);
  3197.   }
  3198. }
  3199.  
  3200.  
  3201.  
  3202. /*****************************************************************************
  3203. *
  3204. * FUNCTION
  3205. *
  3206. *   average_textures
  3207. *
  3208. * INPUT
  3209. *
  3210. * OUTPUT
  3211. *
  3212. * RETURNS
  3213. *
  3214. * AUTHOR
  3215. *
  3216. *   POV-Ray Team
  3217. *
  3218. * DESCRIPTION
  3219. *
  3220. *   -
  3221. *
  3222. * CHANGES
  3223. *
  3224. *   -
  3225. *
  3226. ******************************************************************************/
  3227.  
  3228. static void average_textures (Result_Colour, Texture, IPoint, Raw_Normal,
  3229.   Ray, Weight, Ray_Intersection, Shadow_Flag)
  3230. COLOUR Result_Colour;
  3231. TEXTURE *Texture;
  3232. VECTOR IPoint, Raw_Normal;
  3233. RAY *Ray;
  3234. DBL Weight;
  3235. INTERSECTION *Ray_Intersection;
  3236. int Shadow_Flag;
  3237. {
  3238.    int i;
  3239.    COLOUR LC;
  3240.    BLEND_MAP *Map = Texture->Blend_Map;
  3241.    SNGL Value;
  3242.    SNGL Total = 0.0;
  3243.    DBL rdiv;
  3244.  
  3245.    Make_Colour (Result_Colour, 0.0, 0.0, 0.0);
  3246.  
  3247.    for (i = 0; i < Map->Number_Of_Entries; i++)
  3248.    {
  3249.      Value = Map->Blend_Map_Entries[i].value;
  3250.  
  3251.      do_texture_map (LC,Map->Blend_Map_Entries[i].Vals.Texture, IPoint,Raw_Normal,Ray,Weight,Ray_Intersection,Shadow_Flag);
  3252.  
  3253.      Result_Colour[RED]   += LC[RED]   *Value;
  3254.      Result_Colour[GREEN] += LC[GREEN] *Value;
  3255.      Result_Colour[BLUE]  += LC[BLUE]  *Value;
  3256.      Result_Colour[FILTER]+= LC[FILTER]*Value;
  3257.      Result_Colour[TRANSM]+= LC[TRANSM]*Value;
  3258.  
  3259.      Total += Value;
  3260.    }
  3261.  
  3262.    rdiv = (1.0 / Total);
  3263.    Result_Colour[RED]   *= rdiv;
  3264.    Result_Colour[GREEN] *= rdiv;
  3265.    Result_Colour[BLUE]  *= rdiv;
  3266.    Result_Colour[FILTER]*= rdiv;
  3267.    Result_Colour[TRANSM]*= rdiv;
  3268. /*
  3269.    Result_Colour[RED]   /= Total;
  3270.    Result_Colour[GREEN] /= Total;
  3271.    Result_Colour[BLUE]  /= Total;
  3272.    Result_Colour[FILTER]/= Total;
  3273.    Result_Colour[TRANSM]/= Total;
  3274. */
  3275. }
  3276.  
  3277.  
  3278.  
  3279. /*****************************************************************************
  3280. *
  3281. * FUNCTION
  3282. *
  3283. *   do_light_ray_atmosphere
  3284. *
  3285. * INPUT
  3286. *
  3287. *   Light_Source_Ray - Current ray towards light source
  3288. *   Ray_Intersection - Current intersection with a blocking object
  3289. *   Texture          - Current PNFH texture
  3290. *   Valid_Object     - Flag: 1=a valid object is in the intersection struct
  3291. *
  3292. * OUTPUT
  3293. *
  3294. *   Colour           - Attenuated light source color
  3295. *
  3296. * RETURNS
  3297. *
  3298. * AUTHOR
  3299. *
  3300. *   Dieter Bayer
  3301. *
  3302. * DESCRIPTION
  3303. *
  3304. *   Determine the influence of atmospheric effects on a light source ray.
  3305. *
  3306. * CHANGES
  3307. *
  3308. *   Aug 1995 : Creation.
  3309. *
  3310. ******************************************************************************/
  3311.  
  3312. static void do_light_ray_atmosphere(Light_Source_Ray, Ray_Intersection, Texture, Colour, Valid_Object)
  3313. RAY *Light_Source_Ray;
  3314. INTERSECTION *Ray_Intersection;
  3315. TEXTURE *Texture;
  3316. COLOUR Colour;
  3317. int Valid_Object;
  3318. {
  3319.   int texture_nr;
  3320.   int i, all_hollow;
  3321.  
  3322.   /* Why are we here? */
  3323.  
  3324.   if ((Colour[RED] < BLACK_LEVEL) && (Colour[GREEN] < BLACK_LEVEL) && (Colour[BLUE] < BLACK_LEVEL))
  3325.   {
  3326.     return;
  3327.   }
  3328.  
  3329.   all_hollow = TRUE;
  3330.  
  3331.   for (i = 0; i <= Light_Source_Ray->Containing_Index; i++)
  3332.   {
  3333.     if (!Test_Flag(Light_Source_Ray->Containing_Objects[i], HOLLOW_FLAG))
  3334.     {
  3335.       all_hollow = FALSE;
  3336.  
  3337.       break;
  3338.     }
  3339.   }
  3340.  
  3341.   /* Apply atmospheric effects inside and/or outside any object. */
  3342.  
  3343.   if (all_hollow || (Valid_Object && Test_Flag(Ray_Intersection->Object, HOLLOW_FLAG)))
  3344.   {
  3345.     Do_Finite_Atmosphere(Light_Source_Ray, Ray_Intersection, Colour, TRUE);
  3346.   }
  3347.  
  3348.   /* Handle contained textures. */
  3349.  
  3350.   if (Valid_Object)
  3351.   {
  3352.     if (Light_Source_Ray->Containing_Index == -1)
  3353.     {
  3354.       /* The ray is entering from the atmosphere */
  3355.  
  3356.       Ray_Enter(Light_Source_Ray, Texture, Ray_Intersection->Object);
  3357.     }
  3358.     else
  3359.     {
  3360.       /* The ray is currently inside an object */
  3361.  
  3362.       if ((texture_nr = Texture_In_Ray_Container(Light_Source_Ray, Texture)) >= 0)
  3363.       {
  3364.         /* The ray is leaving the current object */
  3365.  
  3366.         Ray_Exit(Light_Source_Ray, texture_nr);
  3367.       }
  3368.       else
  3369.       {
  3370.         /* The ray is entering a new object */
  3371.  
  3372.         Ray_Enter(Light_Source_Ray, Texture, Ray_Intersection->Object);
  3373.       }
  3374.     }
  3375.   }
  3376. }
  3377.